table_print 0.2.3 → 1.0.0.rc3
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/.rspec +1 -0
- data/.rvmrc +1 -1
- data/.travis.yml +5 -0
- data/Gemfile +11 -10
- data/README.rdoc +85 -32
- data/Rakefile +13 -13
- data/VERSION +1 -1
- data/features/adding_columns.feature +48 -0
- data/features/configuring_output.feature +57 -0
- data/features/excluding_columns.feature +28 -0
- data/features/sensible_defaults.feature +86 -0
- data/features/support/step_definitions/before.rb +3 -0
- data/features/support/step_definitions/steps.rb +77 -0
- data/lib/cattr.rb +46 -0
- data/lib/column.rb +45 -0
- data/lib/config.rb +36 -0
- data/lib/config_resolver.rb +91 -0
- data/lib/fingerprinter.rb +85 -0
- data/lib/formatter.rb +45 -0
- data/lib/hash_extensions.rb +37 -0
- data/lib/kernel_extensions.rb +12 -0
- data/lib/printable.rb +22 -0
- data/lib/returnable.rb +21 -0
- data/lib/row_group.rb +227 -0
- data/lib/table_print.rb +33 -389
- data/spec/column_spec.rb +71 -0
- data/spec/config_resolver_spec.rb +236 -0
- data/spec/config_spec.rb +52 -0
- data/spec/fingerprinter_spec.rb +151 -0
- data/spec/formatter_spec.rb +78 -0
- data/spec/hash_extensions_spec.rb +21 -0
- data/spec/printable_spec.rb +51 -0
- data/spec/returnable_spec.rb +23 -0
- data/spec/row_group_spec.rb +466 -0
- data/spec/spec_helper.rb +8 -0
- data/spec/table_print_spec.rb +59 -0
- data/table_print.gemspec +50 -26
- metadata +147 -68
- data/Gemfile.lock +0 -20
- data/test/helper.rb +0 -56
- data/test/test_column.rb +0 -379
- data/test/test_table_print.rb +0 -162
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.rvmrc
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
# development environment upon cd'ing into the directory
|
5
5
|
|
6
6
|
# First we specify our desired <ruby>[@<gemset>], the @gemset name is optional.
|
7
|
-
environment_id="ruby-1.
|
7
|
+
environment_id="ruby-1.8.7-p358"
|
8
8
|
|
9
9
|
#
|
10
10
|
# Uncomment the following lines if you want to verify rvm version per project
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
-
source
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
source :rubygems
|
2
|
+
|
3
|
+
gemspec :name => 'table_print'
|
4
|
+
|
5
|
+
gem 'bundler', "~> 1.1"
|
5
6
|
|
6
|
-
# Add dependencies to develop your gem here.
|
7
|
-
# Include everything needed to run rake, tests, features, etc.
|
8
7
|
group :development do
|
9
|
-
gem
|
10
|
-
gem "bundler", "~> 1.0.0"
|
11
|
-
gem "jeweler", "~> 1.5.2"
|
12
|
-
gem "rcov", ">= 0"
|
8
|
+
gem 'relish'
|
13
9
|
end
|
10
|
+
|
11
|
+
group :test do
|
12
|
+
gem 'cat', "~> 0.2.1"
|
13
|
+
end
|
14
|
+
|
data/README.rdoc
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
= table_print
|
2
2
|
|
3
|
+
{<img src="https://secure.travis-ci.org/arches/table_print.png" />}[http://travis-ci.org/arches/table_print]
|
4
|
+
|
5
|
+
|
3
6
|
Turn objects into nicely formatted columns for easy reading
|
4
7
|
|
5
8
|
TablePrint formats an object or array of objects into columns for easy reading. To do this,
|
@@ -19,15 +22,16 @@ it assumes the objects in your array all respond to the same methods.
|
|
19
22
|
# Outside rails
|
20
23
|
$ irb
|
21
24
|
> require 'table_print'
|
22
|
-
> tp array_of_objects, options
|
25
|
+
> tp array_of_objects, options
|
23
26
|
|
24
27
|
# Inside rails, the gem has already been required by your Gemfile so all you need to do is
|
25
28
|
$ rails c
|
26
|
-
> tp array_of_objects, options
|
29
|
+
> tp array_of_objects, options
|
27
30
|
|
28
31
|
You should see something like this:
|
29
32
|
|
30
|
-
|
33
|
+
> tp Book.all
|
34
|
+
AUTHOR | SUMMARY | TITLE
|
31
35
|
-----------------------------------------------------------------------
|
32
36
|
Michael Connelly | Another book by Michael Con... | The Fifth Witness
|
33
37
|
Manning Mardale | From acclaimed historian Ma... | Malcolm X
|
@@ -35,63 +39,112 @@ You should see something like this:
|
|
35
39
|
|
36
40
|
TablePrint tries to use sensible defaults to choose the columns to show. If you're inspecting ActiveRecord objects, it
|
37
41
|
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.
|
42
|
+
on your model. Use symbols or strings to reference the columns.
|
39
43
|
|
40
|
-
# Maybe you
|
41
|
-
|
44
|
+
# Maybe you store a user's hourly rate but you want to see their yearly income
|
45
|
+
tp User.limit(30), :include => :yearly_income, :except => :hourly_rate
|
42
46
|
|
43
47
|
# Maybe all you care about is their mailing info
|
44
|
-
|
48
|
+
tp User.limit(30), :address, 'city', 'state', :zip
|
45
49
|
|
46
|
-
If you're not using ActiveRecord, the TablePrint default is to show all the methods on your object
|
47
|
-
|
50
|
+
If you're not using ActiveRecord, the TablePrint default is to show all the methods defined directly on your object (nothing
|
51
|
+
from superclasses/mixins).
|
48
52
|
|
49
53
|
You can reference nested objects with the method chain required to reach them. Say you had some users who wrote books, and those
|
50
54
|
books had photos.
|
51
55
|
|
52
|
-
> tp
|
53
|
-
|
54
|
-
NAME | BOOKS > TITLE | BOOKS > PHOTOS > CAPTION
|
56
|
+
> tp Author.limit(3), "name", "books.title", "books.photos.caption"
|
57
|
+
NAME | BOOKS.TITLE | BOOKS.PHOTOS.CAPTION
|
55
58
|
-------------------------------------------------------------------------
|
56
|
-
Michael Connelly |
|
57
|
-
| The Fifth Witness |
|
58
|
-
| | Susan was running, fast, away...
|
59
|
+
Michael Connelly | The Fifth Witness | Susan was running, fast, away...
|
59
60
|
| | Along came a spider.
|
60
61
|
| Malcolm X |
|
61
|
-
| Bossypants |
|
62
|
-
| | Yes! Yes! A thousand times ye...
|
62
|
+
| Bossypants | Yes! Yes! A thousand times ye...
|
63
63
|
| | Don't see many like you aroun...
|
64
64
|
Carrot Top | |
|
65
|
-
Milton Greene |
|
66
|
-
| How I Learned |
|
67
|
-
| | Once upon a time, I was a sma...
|
65
|
+
Milton Greene | How I Learned | Once upon a time, I was a sma...
|
68
66
|
| | Lemons are yellow, limes are ...
|
69
67
|
| | Never as a woman her age. I l...
|
70
|
-
| Desperados |
|
71
|
-
| | Avast.
|
68
|
+
| Desperados | Avast.
|
72
69
|
| | Giraffes lived a peaceful exi...
|
73
70
|
|
74
71
|
|
75
72
|
=== Column options
|
76
73
|
|
77
74
|
Pass options to individual columns through the options hash by using the display method as the hash key. Eg, if you wanted
|
78
|
-
|
75
|
+
a skinny email column, set the width explicitly:
|
76
|
+
|
77
|
+
tp User.all, :email => {:width => 12}
|
78
|
+
|
79
|
+
Available column options:
|
80
|
+
|
81
|
+
* *display_method* - string/symbol/proc - used to populate the column. Can be a method name or a proc. See below.
|
82
|
+
* *formatters* - array of objects - each will be called in turn as the cells are printed. Must define a 'format' method. See below.
|
83
|
+
* *time_format* - string - passed to strftime[http://www.ruby-doc.org/core-1.9.3/Time.html#method-i-strftime], only affects time columns
|
84
|
+
* *width* - integer - how wide you want your column. Currently cannot exceed max_width.
|
85
|
+
|
86
|
+
==== Display method
|
87
|
+
|
88
|
+
Columns are named after hash keys. To rename a column, use the name you want as the key, and pass the method as an option.
|
89
|
+
|
90
|
+
tp User.all, :active => {:display_method => :active_in_the_past_six_months} # the User class defines active_in_the_past_six_months method
|
91
|
+
|
92
|
+
==== Lambdas
|
93
|
+
|
94
|
+
You can pass a proc as the display_method for a column:
|
79
95
|
|
80
|
-
tp User.all, :
|
96
|
+
tp User.all, :email, :monthly_payment, :yearly_payment => lambda{|u| u.monthly_payment * 12}
|
81
97
|
|
82
|
-
|
98
|
+
Or if you want to pass other options along with the lambda:
|
83
99
|
|
84
|
-
|
100
|
+
tp User.all, :yearly_payment => {:display_method => lambda{|u| u.monthly_payment * 12}, :width => 10}
|
85
101
|
|
86
|
-
|
87
|
-
will ensure that the column is as skinny as possible, but never above the number you provide.
|
102
|
+
==== Column formatters
|
88
103
|
|
89
|
-
|
90
|
-
|
104
|
+
Similar to a lambda column, you can use a column formatter to reuse code across prints. Any object with a 'format' method
|
105
|
+
can be used to filter a column. This could also be used for coloring output.
|
91
106
|
|
107
|
+
class NoNewlineFormatter
|
108
|
+
def format(value)
|
109
|
+
value.to_s.gsub(/\r\n/, " ")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
tp User.all, :bio => {:formatters => [NoNewlineFormatter.new]} # strip newlines from user bios
|
114
|
+
|
115
|
+
|
116
|
+
=== Config
|
117
|
+
|
118
|
+
Use `tp.set` and `tp.clear` to set options on a class-by-class basis.
|
119
|
+
|
120
|
+
tp.set User, :id, :email # now whenever you print users, the only columns shown will be id and email
|
121
|
+
|
122
|
+
> tp User.first
|
123
|
+
ID | EMAIL
|
124
|
+
----------------
|
125
|
+
1 | foo@bar.com
|
126
|
+
|
127
|
+
# the config sets a 'baseline' for each print. You can still include/except columns:
|
128
|
+
> tp User.first, :except => :email
|
129
|
+
ID
|
130
|
+
--
|
131
|
+
17
|
132
|
+
|
133
|
+
# you can still provide a specific set of columns:
|
134
|
+
> tp User.first, :first_name
|
135
|
+
FIRST_NAME
|
136
|
+
----------
|
137
|
+
Phooey
|
138
|
+
|
139
|
+
tp.clear User # back to square one - print all the columns we can find
|
140
|
+
|
141
|
+
You can also set individual options:
|
142
|
+
|
143
|
+
tp.set :max_width, 10 # columns won't exceed 10 characters
|
144
|
+
tp.set :time_format, "%Y" # date columns will only show the year
|
92
145
|
|
93
146
|
== Contributing to table_print
|
94
|
-
|
147
|
+
|
95
148
|
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
96
149
|
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
97
150
|
* Fork the project
|
@@ -102,5 +155,5 @@ it contains. The max_field_length option takes precedence over field_length - ie
|
|
102
155
|
|
103
156
|
== Copyright
|
104
157
|
|
105
|
-
Copyright (c)
|
158
|
+
Copyright (c) 2012 Chris Doyle. See LICENSE.txt for further details.
|
106
159
|
|
data/Rakefile
CHANGED
@@ -22,25 +22,25 @@ Jeweler::Tasks.new do |gem|
|
|
22
22
|
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
23
|
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
24
|
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
25
|
-
|
25
|
+
gem.add_development_dependency 'rspec'
|
26
|
+
gem.add_development_dependency 'cucumber'
|
26
27
|
end
|
27
28
|
Jeweler::RubygemsDotOrgTasks.new
|
28
29
|
|
29
|
-
require '
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
test.verbose = true
|
34
|
-
end
|
30
|
+
require 'rspec/core/rake_task'
|
31
|
+
|
32
|
+
desc 'Default: run specs and cucumber features.'
|
33
|
+
task :default => [:spec, :cucumber]
|
35
34
|
|
36
|
-
|
37
|
-
|
38
|
-
test.libs << 'test'
|
39
|
-
test.pattern = 'test/**/test_*.rb'
|
40
|
-
test.verbose = true
|
35
|
+
desc "Run specs"
|
36
|
+
RSpec::Core::RakeTask.new do |t|
|
41
37
|
end
|
42
38
|
|
43
|
-
task
|
39
|
+
require "cucumber/rake/task"
|
40
|
+
desc 'Run cucumber features'
|
41
|
+
Cucumber::Rake::Task.new(:cucumber) do |task|
|
42
|
+
task.cucumber_opts = ["features"]
|
43
|
+
end
|
44
44
|
|
45
45
|
begin
|
46
46
|
require 'rdoc/task'
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
1.0.0.rc3
|
@@ -0,0 +1,48 @@
|
|
1
|
+
Feature: Adding columns
|
2
|
+
Scenario: With the :include option
|
3
|
+
Given a class named Foo
|
4
|
+
Given Foo has attributes herp, blog
|
5
|
+
|
6
|
+
Given a class named Foo::Blog
|
7
|
+
Given Foo::Blog has attributes title, author
|
8
|
+
Given Foo::Blog has a class method named foo with lambda{"just testing!"}
|
9
|
+
Given Foo::Blog has a method named two_args with lambda{|a, b| "Called with #{a}, #{b}"}
|
10
|
+
|
11
|
+
When I instantiate a Foo with {:herp => "derp"}
|
12
|
+
When I instantiate a Foo::Blog with {:title => "post!", :author => 'Ryan'} and assign it to foo.blog
|
13
|
+
And table_print Foo, {:include => ["blog.author", "blog.title"]}
|
14
|
+
Then the output should contain
|
15
|
+
"""
|
16
|
+
HERP | BLOG.AUTHOR | BLOG.TITLE
|
17
|
+
-------------------------------
|
18
|
+
derp | Ryan | post!
|
19
|
+
"""
|
20
|
+
|
21
|
+
Scenario: Providing a named proc
|
22
|
+
Given a class named Blog
|
23
|
+
|
24
|
+
Given Blog has attributes title, author
|
25
|
+
|
26
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan'}
|
27
|
+
And table_print Blog, {:wombat => {:display_method => lambda{|blog| blog.author.gsub(/[aeiou]/, "").downcase}}}
|
28
|
+
Then the output should contain
|
29
|
+
"""
|
30
|
+
WOMBAT
|
31
|
+
------
|
32
|
+
ryn
|
33
|
+
"""
|
34
|
+
Scenario: Providing a named proc without saying 'display_method', eg :foo => lambda{}
|
35
|
+
Given a class named Blog
|
36
|
+
|
37
|
+
Given Blog has attributes title, author
|
38
|
+
|
39
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan'}
|
40
|
+
And table_print Blog, {:wombat => lambda{|blog| blog.author.gsub(/[aeiou]/, "").downcase}}
|
41
|
+
Then the output should contain
|
42
|
+
"""
|
43
|
+
WOMBAT
|
44
|
+
------
|
45
|
+
ryn
|
46
|
+
"""
|
47
|
+
Scenario: Using a proc as a filter (ie, overriding an existing column with a proc)
|
48
|
+
|
@@ -0,0 +1,57 @@
|
|
1
|
+
Feature: Configuring output
|
2
|
+
Scenario: Setting a (max? or specific?) width for all columns
|
3
|
+
Scenario: Setting a specific width for an individual column
|
4
|
+
Given a class named Blog
|
5
|
+
|
6
|
+
Given Blog has attributes title, author
|
7
|
+
|
8
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan'}
|
9
|
+
And table_print Blog, {:include => {:author => {:width => 10}}}
|
10
|
+
Then the output should contain
|
11
|
+
"""
|
12
|
+
TITLE | AUTHOR
|
13
|
+
------------------
|
14
|
+
post! | Ryan
|
15
|
+
"""
|
16
|
+
Scenario: Specifying configuration on a per-object basis
|
17
|
+
Given a class named Blog
|
18
|
+
|
19
|
+
Given Blog has attributes title, author
|
20
|
+
|
21
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan'}
|
22
|
+
And configure Blog with :title
|
23
|
+
And table_print Blog
|
24
|
+
Then the output should contain
|
25
|
+
"""
|
26
|
+
TITLE
|
27
|
+
-----
|
28
|
+
post!
|
29
|
+
"""
|
30
|
+
Scenario: Specifying configuration on a per-object basis with an included column
|
31
|
+
Given a class named Blog
|
32
|
+
|
33
|
+
Given Blog has attributes title, author
|
34
|
+
|
35
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan'}
|
36
|
+
And configure Blog with {:include => {:foobar => lambda{|b| b.title}}}
|
37
|
+
And table_print Blog
|
38
|
+
Then the output should contain
|
39
|
+
"""
|
40
|
+
TITLE | AUTHOR | FOOBAR
|
41
|
+
-----------------------
|
42
|
+
post! | Ryan | post!
|
43
|
+
"""
|
44
|
+
Scenario: Applying a formatter
|
45
|
+
Scenario: Setting a column name
|
46
|
+
Given a class named Blog
|
47
|
+
|
48
|
+
Given Blog has attributes title, author
|
49
|
+
|
50
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan'}
|
51
|
+
And table_print Blog, {:wombat => {:display_method => :author}}
|
52
|
+
Then the output should contain
|
53
|
+
"""
|
54
|
+
WOMBAT
|
55
|
+
------
|
56
|
+
Ryan
|
57
|
+
"""
|
@@ -0,0 +1,28 @@
|
|
1
|
+
Feature: Excluding columns
|
2
|
+
Scenario: With the :except option
|
3
|
+
Given a class named Blog
|
4
|
+
|
5
|
+
Given Blog has attributes title, author
|
6
|
+
|
7
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan'}
|
8
|
+
And table_print Blog, {:except => :title}
|
9
|
+
Then the output should contain
|
10
|
+
"""
|
11
|
+
AUTHOR
|
12
|
+
------
|
13
|
+
Ryan
|
14
|
+
"""
|
15
|
+
|
16
|
+
Scenario: By specifying columns
|
17
|
+
Given a class named Blog
|
18
|
+
|
19
|
+
Given Blog has attributes title, author, url
|
20
|
+
|
21
|
+
When I instantiate a Blog with {:title => "post!", :author => 'Ryan', :url => "http://google.com"}
|
22
|
+
And table_print Blog, [:author, :url]
|
23
|
+
Then the output should contain
|
24
|
+
"""
|
25
|
+
AUTHOR | URL
|
26
|
+
--------------------------
|
27
|
+
Ryan | http://google.com
|
28
|
+
"""
|
@@ -0,0 +1,86 @@
|
|
1
|
+
Feature: Sensible defaults
|
2
|
+
|
3
|
+
By default, table_print shows all "getter" methods defined on your object itself. This includes anything except:
|
4
|
+
|
5
|
+
* Methods defined in an object's parent class
|
6
|
+
* Methods defined in an object's included modules
|
7
|
+
* Methods whose name ends with an equals sign (ie, setter methods)
|
8
|
+
* Methods with an arity > 0 (ie, methods that take arguments)
|
9
|
+
|
10
|
+
Scenario: A simple object
|
11
|
+
Given a class named Foo
|
12
|
+
Given Foo has attributes herp
|
13
|
+
Given Foo has a method named derp with lambda{"hurrrrr"}
|
14
|
+
|
15
|
+
Given a class named Foo::Blog
|
16
|
+
Given Foo::Blog has attributes title, author
|
17
|
+
Given Foo::Blog has a class method named foo with lambda{"just testing!"}
|
18
|
+
Given Foo::Blog has a method named two_args with lambda{|a, b| "Called with #{a}, #{b}"}
|
19
|
+
|
20
|
+
When I instantiate a Foo::Blog with {:title => "First post!", :author => 'Ryan'}
|
21
|
+
And table_print Foo::Blog
|
22
|
+
Then the output should contain
|
23
|
+
"""
|
24
|
+
TITLE | AUTHOR
|
25
|
+
--------------------
|
26
|
+
First post! | Ryan
|
27
|
+
"""
|
28
|
+
|
29
|
+
Scenario: An array of objects
|
30
|
+
Given a class named Post
|
31
|
+
Given Post has attributes title, author
|
32
|
+
Given Post has a class method named foo with lambda{"just testing!"}
|
33
|
+
Given Post has a method named two_args with lambda{|a, b| "Called with #{a}, #{b}"}
|
34
|
+
|
35
|
+
Given a class named Blog
|
36
|
+
Given Blog has attributes posts
|
37
|
+
|
38
|
+
When I instantiate a Blog with {:posts => []}
|
39
|
+
When I instantiate a Post with {:title => "First post!", :author => 'Ryan'} and add it to blog.posts
|
40
|
+
When I instantiate a Post with {:title => "Second post!", :author => 'Ryan'} and add it to blog.posts
|
41
|
+
When I instantiate a Post with {:title => "Third post!", :author => 'Ryan'} and add it to blog.posts
|
42
|
+
And table_print blog.posts
|
43
|
+
Then the output should contain
|
44
|
+
"""
|
45
|
+
TITLE | AUTHOR
|
46
|
+
---------------------
|
47
|
+
First post! | Ryan
|
48
|
+
Second post! | Ryan
|
49
|
+
Third post! | Ryan
|
50
|
+
"""
|
51
|
+
|
52
|
+
Scenario: Nested objects
|
53
|
+
Given a class named Comment
|
54
|
+
Given Comment has attributes id, username, body
|
55
|
+
|
56
|
+
Given a class named Blog
|
57
|
+
Given Blog has attributes id, comments
|
58
|
+
|
59
|
+
Given I instantiate a Blog with {:id => 1, :comments => []}
|
60
|
+
And I instantiate a Comment with {:id => 1, :username => 'chris', :body => 'once upon a time'} and add it to blog.comments
|
61
|
+
And I instantiate a Comment with {:id => 2, :username => 'joe', :body => 'once upon a time'} and add it to blog.comments
|
62
|
+
When I table_print Blog, [:id, "comments.id", "comments.username"]
|
63
|
+
Then the output should contain
|
64
|
+
"""
|
65
|
+
ID | COMMENTS.ID | COMMENTS.USERNAME
|
66
|
+
------------------------------------
|
67
|
+
1 | 1 | chris
|
68
|
+
| 2 | joe
|
69
|
+
"""
|
70
|
+
|
71
|
+
Scenario: An object with column info (like an ActiveRecord object)
|
72
|
+
Given a class named ColumnInfo
|
73
|
+
Given ColumnInfo has attributes name
|
74
|
+
|
75
|
+
Given a class named Blog
|
76
|
+
Given Blog has attributes title, author
|
77
|
+
Given Blog has a class method named columns with lambda{[Sandbox::ColumnInfo.new(:name => :title)]}
|
78
|
+
|
79
|
+
When I instantiate a Blog with {:title => "First post!", :author => 'Ryan'}
|
80
|
+
And table_print Blog
|
81
|
+
Then the output should contain
|
82
|
+
"""
|
83
|
+
TITLE
|
84
|
+
-----------
|
85
|
+
First post!
|
86
|
+
"""
|