ruport 0.4.23 → 0.4.99
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/AUTHORS +16 -8
- data/CHANGELOG +30 -1
- data/README +144 -114
- data/Rakefile +12 -4
- data/TODO +4 -7
- data/bin/rope +21 -28
- data/examples/line_graph.rb +36 -0
- data/examples/sample_invoice_report.rb +1 -1
- data/examples/simple_graph.rb +8 -0
- data/lib/SVG/Graph/Bar.rb +137 -0
- data/lib/SVG/Graph/BarBase.rb +140 -0
- data/lib/SVG/Graph/BarHorizontal.rb +136 -0
- data/lib/SVG/Graph/Graph.rb +977 -0
- data/lib/SVG/Graph/Line.rb +444 -0
- data/lib/SVG/Graph/Pie.rb +394 -0
- data/lib/SVG/Graph/Plot.rb +494 -0
- data/lib/SVG/Graph/Schedule.rb +373 -0
- data/lib/SVG/Graph/TimeSeries.rb +241 -0
- data/lib/ruport.rb +2 -2
- data/lib/ruport/config.rb +47 -3
- data/lib/ruport/data/collection.rb +17 -1
- data/lib/ruport/data/record.rb +101 -8
- data/lib/ruport/data/set.rb +81 -2
- data/lib/ruport/data/set.rb.rej +147 -0
- data/lib/ruport/data/set.rb~ +73 -0
- data/lib/ruport/data/table.rb +127 -2
- data/lib/ruport/data/taggable.rb +21 -2
- data/lib/ruport/format.rb +36 -44
- data/lib/ruport/format/engine.rb +21 -1
- data/lib/ruport/format/plugin.rb +64 -1
- data/lib/ruport/mailer.rb +70 -36
- data/lib/ruport/meta_tools.rb +15 -6
- data/lib/ruport/query.rb +1 -1
- data/lib/ruport/rails/reportable.rb +23 -1
- data/lib/ruport/report.rb +11 -11
- data/lib/ruport/report/invoice.rb +16 -0
- data/lib/ruport/system_extensions.rb +3 -55
- data/test/{tc_database.rb → _test_database.rb} +0 -0
- data/test/{tc_config.rb → test_config.rb} +0 -0
- data/test/{tc_format.rb → test_format.rb} +1 -0
- data/test/{tc_format_engine.rb → test_format_engine.rb} +14 -2
- data/test/test_graph.rb +101 -0
- data/test/{tc_invoice.rb → test_invoice.rb} +7 -1
- data/test/test_mailer.rb +108 -0
- data/test/test_meta_tools.rb +14 -0
- data/test/{tc_plugin.rb → test_plugin.rb} +12 -1
- data/test/{tc_query.rb → test_query.rb} +0 -0
- data/test/{tc_record.rb → test_record.rb} +9 -0
- data/test/{tc_report.rb → test_report.rb} +2 -1
- data/test/{tc_ruport.rb → test_ruport.rb} +0 -0
- data/test/test_set.rb +118 -0
- data/test/test_set.rb.rej +16 -0
- data/test/{tc_set.rb → test_set.rb~} +17 -0
- data/test/{tc_sql_split.rb → test_sql_split.rb} +0 -0
- data/test/{tc_table.rb → test_table.rb} +15 -0
- data/test/{tc_taggable.rb → test_taggable.rb} +0 -0
- data/test/unit.log +361 -0
- metadata +52 -30
- data/examples/bar.pdf +0 -193
- data/examples/f.log +0 -5
- data/examples/foo.pdf +0 -193
- data/lib/ruport/format/document.rb +0 -78
- data/lib/ruport/format/open_node.rb +0 -38
- data/test/tc_data_row.rb +0 -132
- data/test/tc_data_set.rb +0 -386
- data/test/tc_document.rb +0 -42
- data/test/tc_element.rb +0 -18
- data/test/tc_page.rb +0 -42
- data/test/tc_section.rb +0 -45
- data/test/ts_all.rb +0 -12
- data/test/ts_format.rb +0 -7
@@ -1,10 +1,26 @@
|
|
1
1
|
module Ruport
|
2
2
|
class Report
|
3
3
|
module Invoice
|
4
|
+
|
5
|
+
# Returns a Format::Engine::Invoice object
|
6
|
+
#
|
7
|
+
# If a block is given, it is possible to customize this object before it
|
8
|
+
# is returned
|
9
|
+
#
|
10
|
+
# Example:
|
11
|
+
#
|
12
|
+
# inv = build_invoice do |i|
|
13
|
+
# i.company_info = "Foo Inc.\n42 Front Street\nNew Haven CT"
|
14
|
+
# i.customer_info = "Joe User\njoe@test.com"
|
15
|
+
# i.data = [["Aspirin","$2.00"]].to_table(%w[item cost])
|
16
|
+
# end
|
4
17
|
def build_invoice
|
5
18
|
a = Ruport::Format.invoice_object(:plugin => :pdf)
|
6
19
|
yield(a); return a
|
7
20
|
end
|
21
|
+
|
22
|
+
# Takes a block and calls build_invoice then calls render on the resulting
|
23
|
+
# Format::Engine::Invoice object
|
8
24
|
def render_invoice(&block)
|
9
25
|
build_invoice(&block).render
|
10
26
|
end
|
@@ -9,6 +9,9 @@
|
|
9
9
|
# - Outer Module is changed from HighLine to Ruport
|
10
10
|
# - terminal_width / terminal_height added
|
11
11
|
#
|
12
|
+
# The following modifications have been made by Gregory Brown on 2006.08.13
|
13
|
+
# - removed most methods, preserving only terminal geometry features
|
14
|
+
#
|
12
15
|
# All modifications are under the distributions terms of Ruport.
|
13
16
|
# Copyright 2006, Gregory Brown. All Rights Reserved
|
14
17
|
#
|
@@ -32,18 +35,6 @@ module Ruport
|
|
32
35
|
begin
|
33
36
|
require "Win32API" # See if we're on Windows.
|
34
37
|
|
35
|
-
CHARACTER_MODE = "Win32API" # For Debugging purposes only.
|
36
|
-
|
37
|
-
#
|
38
|
-
# Windows savvy getc().
|
39
|
-
#
|
40
|
-
# *WARNING*: This method ignores <tt>input</tt> and reads one
|
41
|
-
# character from +STDIN+!
|
42
|
-
#
|
43
|
-
def get_character( input = STDIN )
|
44
|
-
Win32API.new("crtdll", "_getch", [ ], "L").Call
|
45
|
-
end
|
46
|
-
|
47
38
|
# A Windows savvy method to fetch the console columns, and rows.
|
48
39
|
def terminal_size
|
49
40
|
m_GetStdHandle = Win32API.new( 'kernel32',
|
@@ -64,49 +55,6 @@ module Ruport
|
|
64
55
|
return right - left + 1, bottom - top + 1
|
65
56
|
end
|
66
57
|
rescue LoadError # If we're not on Windows try...
|
67
|
-
begin
|
68
|
-
require "termios" # Unix, first choice.
|
69
|
-
|
70
|
-
CHARACTER_MODE = "termios" # For Debugging purposes only.
|
71
|
-
|
72
|
-
#
|
73
|
-
# Unix savvy getc(). (First choice.)
|
74
|
-
#
|
75
|
-
# *WARNING*: This method requires the "termios" library!
|
76
|
-
#
|
77
|
-
def get_character( input = STDIN )
|
78
|
-
old_settings = Termios.getattr(input)
|
79
|
-
|
80
|
-
new_settings = old_settings.dup
|
81
|
-
new_settings.c_lflag &= ~(Termios::ECHO | Termios::ICANON)
|
82
|
-
|
83
|
-
begin
|
84
|
-
Termios.setattr(input, Termios::TCSANOW, new_settings)
|
85
|
-
input.getc
|
86
|
-
ensure
|
87
|
-
Termios.setattr(input, Termios::TCSANOW, old_settings)
|
88
|
-
end
|
89
|
-
end
|
90
|
-
rescue LoadError # If our first choice fails, default.
|
91
|
-
CHARACTER_MODE = "stty" # For Debugging purposes only.
|
92
|
-
|
93
|
-
#
|
94
|
-
# Unix savvy getc(). (Second choice.)
|
95
|
-
#
|
96
|
-
# *WARNING*: This method requires the external "stty" program!
|
97
|
-
#
|
98
|
-
def get_character( input = STDIN )
|
99
|
-
state = `stty -g`
|
100
|
-
|
101
|
-
begin
|
102
|
-
system "stty raw -echo cbreak"
|
103
|
-
input.getc
|
104
|
-
ensure
|
105
|
-
system "stty #{state}"
|
106
|
-
end
|
107
|
-
end
|
108
|
-
end
|
109
|
-
|
110
58
|
# A Unix savvy method to fetch the console columns, and rows.
|
111
59
|
def terminal_size
|
112
60
|
`stty size`.split.map { |x| x.to_i }.reverse
|
File without changes
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
|
-
require 'rubygems' rescue LoadError nil
|
2
1
|
require 'ruport'
|
2
|
+
require 'rubygems' rescue LoadError nil
|
3
3
|
require 'test/unit'
|
4
4
|
|
5
5
|
class MockPlugin < Ruport::Format::Plugin
|
@@ -75,6 +75,15 @@ class TestTabularFormatEngine < Test::Unit::TestCase
|
|
75
75
|
assert_equal "#{@engine.data}", @engine.render
|
76
76
|
end
|
77
77
|
|
78
|
+
# test that attempting to render using an invalid plugin returns an exception
|
79
|
+
# with a useful message
|
80
|
+
def test_render_with_invalid_plugin
|
81
|
+
assert_raises(InvalidPluginError) {
|
82
|
+
Format.table(:plugin => :monkeys,
|
83
|
+
:data => [[1,2,3],[4,5,6],[7,8,9]].to_table(%w[a b c]))
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
78
87
|
def test_simple_interface
|
79
88
|
expected = "#{[[1,2],[3,4]]}"
|
80
89
|
actual = Format.table(:plugin => :mock, :data => [[1,2],[3,4]])
|
@@ -138,7 +147,7 @@ class TestTabularFormatEngine < Test::Unit::TestCase
|
|
138
147
|
assert_equal( [[1,2,3],[nil,2,4],[nil,3,7],
|
139
148
|
[2,1,9],[nil,2,3],[nil,2,9]], @engine.data)
|
140
149
|
|
141
|
-
data = Data::Table.new :column_names => %w[name date service amount]
|
150
|
+
data = Ruport::Data::Table.new :column_names => %w[name date service amount]
|
142
151
|
data << [ "Greg Gibson", "1/1/2000", "Prophy", "100.00" ] <<
|
143
152
|
[ "Greg Gibson", "1/1/2000", "Filling", "100.00" ] <<
|
144
153
|
[ "Greg Gibson", "1/12/2000", "Prophy", "100.00" ] <<
|
@@ -163,6 +172,9 @@ class TestTabularFormatEngine < Test::Unit::TestCase
|
|
163
172
|
end
|
164
173
|
|
165
174
|
class TestDocumentFormatEngine < Test::Unit::TestCase
|
175
|
+
|
176
|
+
include Ruport
|
177
|
+
|
166
178
|
def setup
|
167
179
|
@engine = Format::Engine::Document.dup
|
168
180
|
end
|
data/test/test_graph.rb
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
require "ruport"
|
2
|
+
require 'rubygems' rescue LoadError nil
|
3
|
+
require "test/unit"
|
4
|
+
|
5
|
+
class TestGraph < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@data = [[1,2,3,2],[3,4,5,6]].to_table(%w[a b c d])
|
9
|
+
@data_mismatched_headings = [[3,2],[3,4]].to_table(%w[a b c])
|
10
|
+
@data_float = [[1.3,2],[3.28322,4]].to_table(%w[a b])
|
11
|
+
@data_not_numbers = [["d",:sdfs,"not a number","1"],[3,4,5,6]].to_table(%w[a b c d])
|
12
|
+
end
|
13
|
+
|
14
|
+
# basic test to ensure bar charts render
|
15
|
+
def test_bar
|
16
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data
|
17
|
+
graph.options = {:graph_style => :bar}
|
18
|
+
output = graph.render
|
19
|
+
|
20
|
+
assert_not_equal nil, output
|
21
|
+
end
|
22
|
+
|
23
|
+
# basic test to ensure horizontal pie charts render
|
24
|
+
def test_bar_horizontal
|
25
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data
|
26
|
+
graph.options = {:graph_style => :bar_horizontal}
|
27
|
+
output = graph.render
|
28
|
+
|
29
|
+
assert_not_equal nil, output
|
30
|
+
end
|
31
|
+
|
32
|
+
# basic test to ensure line charts render
|
33
|
+
def test_line
|
34
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data
|
35
|
+
graph.options = {:graph_style => :line}
|
36
|
+
output = graph.render
|
37
|
+
|
38
|
+
assert_not_equal nil, output
|
39
|
+
end
|
40
|
+
|
41
|
+
# basic test to ensure pie charts render
|
42
|
+
def test_pie
|
43
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data
|
44
|
+
graph.options = {:graph_style => :pie}
|
45
|
+
output = graph.render
|
46
|
+
|
47
|
+
assert_not_equal nil, output
|
48
|
+
end
|
49
|
+
|
50
|
+
# ensure an exception is raised if the user doesn't name every column
|
51
|
+
def test_mismatched_headings
|
52
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data_mismatched_headings
|
53
|
+
graph.options = {:graph_style => :line}
|
54
|
+
|
55
|
+
assert_raises(ArgumentError) {
|
56
|
+
output = graph.render
|
57
|
+
}
|
58
|
+
end
|
59
|
+
|
60
|
+
# test to ensure floats can be graphed
|
61
|
+
def test_floats
|
62
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data_float
|
63
|
+
graph.options = {:graph_style => :line}
|
64
|
+
output = graph.render
|
65
|
+
|
66
|
+
assert_not_equal nil, output
|
67
|
+
end
|
68
|
+
|
69
|
+
# ensure an exception is raised if non numeric data is graphed
|
70
|
+
def test_not_numbers
|
71
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data_not_numbers
|
72
|
+
graph.options = {:graph_style => :line}
|
73
|
+
|
74
|
+
assert_raises(ArgumentError) {
|
75
|
+
output = graph.render
|
76
|
+
}
|
77
|
+
end
|
78
|
+
|
79
|
+
# ensure an exception is raised if user tries to render a graph without setting any options
|
80
|
+
def test_no_options
|
81
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data
|
82
|
+
|
83
|
+
assert_raises(RuntimeError) {
|
84
|
+
output = graph.render
|
85
|
+
}
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
# test to make sure user requested options are applied to the resulting graph
|
90
|
+
def test_options_applied_to_rendered_graph
|
91
|
+
graph = Ruport::Format.graph_object :plugin => :svg, :data => @data
|
92
|
+
graph.options = {:graph_style => :line, :graph_title => 'Test', :show_graph_title => true, :no_css => true}
|
93
|
+
output = graph.render
|
94
|
+
|
95
|
+
# ensure the requested graph title is included in the SVG output. If that's there, we can
|
96
|
+
# assume the rest are as well
|
97
|
+
assert_not_equal nil, output[/class='mainTitle'/]
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
end
|
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'ruport'
|
1
2
|
require 'rubygems' rescue LoadError nil
|
2
3
|
require "test/unit"
|
3
4
|
|
@@ -6,8 +7,13 @@ class SampleInvoiceReport < Ruport::Report
|
|
6
7
|
end
|
7
8
|
|
8
9
|
class TestInvoice < Test::Unit::TestCase
|
9
|
-
|
10
|
+
|
10
11
|
def test_basic
|
12
|
+
begin
|
13
|
+
require "pdf/writer"
|
14
|
+
rescue LoadError
|
15
|
+
warn "skipping pdf test"; return
|
16
|
+
end
|
11
17
|
inv = SampleInvoiceReport.build_invoice do |i|
|
12
18
|
i.company_info = "Foo Inc.\n42 Bar Street\nBaz, CT\n"
|
13
19
|
i.customer_info = "Gregory Brown\ngregory.t.brown@gmail.com"
|
data/test/test_mailer.rb
ADDED
@@ -0,0 +1,108 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "ruport"
|
3
|
+
begin; require "rubygems"; rescue LoadError; nil end
|
4
|
+
|
5
|
+
class TestMailer < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def setup
|
8
|
+
@default_opts = {
|
9
|
+
:host => "mail.example.com",
|
10
|
+
:address => "sue@example.com",
|
11
|
+
:user => "inky",
|
12
|
+
:password => "chunky"
|
13
|
+
}
|
14
|
+
|
15
|
+
@other_opts = {
|
16
|
+
:host => "moremail.example.com",
|
17
|
+
:address => "clyde@example.com",
|
18
|
+
:user => "blinky",
|
19
|
+
:password => "bacon"
|
20
|
+
}
|
21
|
+
|
22
|
+
Ruport::Config.mailer :default, @default_opts
|
23
|
+
Ruport::Config.mailer :other, @other_opts
|
24
|
+
|
25
|
+
@default_mailer = Ruport::Mailer.new
|
26
|
+
@other_mailer = Ruport::Mailer.new :other
|
27
|
+
end
|
28
|
+
|
29
|
+
def assert_mailer_equal(expected, mailer)
|
30
|
+
assert_equal expected[:host], mailer.instance_variable_get(:@host)
|
31
|
+
assert_equal expected[:address], mailer.instance_variable_get(:@address)
|
32
|
+
assert_equal expected[:user], mailer.instance_variable_get(:@user)
|
33
|
+
assert_equal expected[:password], mailer.instance_variable_get(:@password)
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_default_constructor
|
37
|
+
assert_mailer_equal @default_opts, @default_mailer
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_constructor_with_mailer_label
|
41
|
+
assert_mailer_equal @other_opts, @other_mailer
|
42
|
+
end
|
43
|
+
|
44
|
+
def test_select_mailer
|
45
|
+
mailer = Ruport::Mailer.new :default
|
46
|
+
assert_mailer_equal @default_opts, mailer
|
47
|
+
|
48
|
+
mailer.send(:select_mailer, :other)
|
49
|
+
assert_mailer_equal @other_opts, mailer
|
50
|
+
end
|
51
|
+
|
52
|
+
def test_to
|
53
|
+
@default_mailer.instance_eval "@mail.to = ['foo@bar.com']"
|
54
|
+
assert_equal ['foo@bar.com'], @default_mailer.to
|
55
|
+
end
|
56
|
+
|
57
|
+
def test_to_equals
|
58
|
+
@default_mailer.to = ['foo@bar.com']
|
59
|
+
assert_equal ['foo@bar.com'], @default_mailer.to
|
60
|
+
end
|
61
|
+
|
62
|
+
def test_from
|
63
|
+
@default_mailer.instance_eval "@mail.from = ['foo@bar.com']"
|
64
|
+
assert_equal ['foo@bar.com'], @default_mailer.from
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_from_equals
|
68
|
+
@default_mailer.from = ['foo@bar.com']
|
69
|
+
assert_equal ['foo@bar.com'], @default_mailer.from
|
70
|
+
end
|
71
|
+
|
72
|
+
def test_subject
|
73
|
+
@default_mailer.instance_eval "@mail.subject = ['RuportDay!']"
|
74
|
+
assert_equal ['RuportDay!'], @default_mailer.subject
|
75
|
+
end
|
76
|
+
|
77
|
+
def test_subject_equals
|
78
|
+
@default_mailer.subject = ['RuportDay!']
|
79
|
+
assert_equal ['RuportDay!'], @default_mailer.subject
|
80
|
+
end
|
81
|
+
|
82
|
+
# def test_html
|
83
|
+
# @default_mailer.instance_eval "@mail.html = 'RuportDay!'"
|
84
|
+
# assert_equal 'RuportDay!', @default_mailer.html
|
85
|
+
# end
|
86
|
+
#
|
87
|
+
# def test_html_equals
|
88
|
+
# @default_mailer.html = 'RuportDay!'
|
89
|
+
# assert_equal 'RuportDay!', @default_mailer.html
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
# def test_text
|
93
|
+
# @default_mailer.instance_eval "@mail.text = 'RuportDay!'"
|
94
|
+
# assert_equal 'RuportDay!', @default_mailer.text
|
95
|
+
# end
|
96
|
+
#
|
97
|
+
# def test_text_equals
|
98
|
+
# @default_mailer.text = 'RuportDay!'
|
99
|
+
# assert_equal 'RuportDay!', @default_mailer.text
|
100
|
+
# end
|
101
|
+
|
102
|
+
def test_no_default
|
103
|
+
Ruport::Config.mailers[:default] = nil
|
104
|
+
assert_raise(RuntimeError){ Ruport::Mailer.new }
|
105
|
+
end
|
106
|
+
|
107
|
+
end
|
108
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
require "ruport"
|
3
|
+
|
4
|
+
class A; extend Ruport::MetaTools; end
|
5
|
+
|
6
|
+
class TestMetaTools < Test::Unit::TestCase
|
7
|
+
|
8
|
+
def test_action
|
9
|
+
assert_nothing_raised { A.action(:foo) { |x| x + 1 } }
|
10
|
+
assert_equal 4, A.foo(3)
|
11
|
+
assert_raise(ActionAlreadyDefinedError) { A.action(:foo) { } }
|
12
|
+
end
|
13
|
+
|
14
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require "test/unit"
|
2
2
|
require "ruport"
|
3
|
-
|
3
|
+
require "rubygems" rescue LoadError nil
|
4
4
|
|
5
5
|
include Ruport
|
6
6
|
|
@@ -49,6 +49,11 @@ end
|
|
49
49
|
class PDFPluginTest < Test::Unit::TestCase
|
50
50
|
|
51
51
|
def test_ensure_fails_on_array
|
52
|
+
begin
|
53
|
+
require "pdf/writer"
|
54
|
+
rescue LoadError
|
55
|
+
warn "skipping pdf test"; return
|
56
|
+
end
|
52
57
|
a = Format.table_object :plugin => :pdf, :data => [[1,2],[3,4]]
|
53
58
|
assert_raise(RuntimeError) { a.render }
|
54
59
|
|
@@ -61,6 +66,12 @@ class PDFPluginTest < Test::Unit::TestCase
|
|
61
66
|
end
|
62
67
|
|
63
68
|
def test_hooks
|
69
|
+
begin
|
70
|
+
require "pdf/writer"
|
71
|
+
rescue LoadError
|
72
|
+
warn "skipping pdf test"; return
|
73
|
+
end
|
74
|
+
a = Format.table_object :plugin => :pdf, :data => [[1,2],[3,4]]
|
64
75
|
a = Format.table_object :plugin => :pdf,
|
65
76
|
:data => [[1,2],[3,4]].to_table(:column_names => %w[a b])
|
66
77
|
y = 0
|
File without changes
|
@@ -135,6 +135,15 @@ class RecordTest < Test::Unit::TestCase
|
|
135
135
|
@record.reorder! 3,1,2
|
136
136
|
assert_equal [3,4,2], @record.data
|
137
137
|
assert_equal %w[c d b], @record.attributes
|
138
|
+
|
139
|
+
r.reorder! %w[a b c]
|
140
|
+
assert_equal [1,2,3], r.data
|
141
|
+
assert_equal %w[a b c], r.attributes
|
142
|
+
|
143
|
+
assert_raise(ArgumentError) { r.reorder "foo" }
|
144
|
+
assert_raise(ArgumentError) { r.reorder 0,5 }
|
145
|
+
assert_nothing_raised { r.reorder 0 }
|
146
|
+
assert_nothing_raised { r.reorder "a","b" }
|
138
147
|
end
|
139
148
|
|
140
149
|
def test_dup
|