hotwire 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.markdown +4 -0
- data/VERSION +1 -1
- data/hotwire.gemspec +2 -2
- data/lib/hotwire/response/base.rb +96 -9
- data/test/response/test_base.rb +67 -5
- metadata +4 -4
data/README.markdown
CHANGED
@@ -59,6 +59,10 @@ The following is a basic example of use.
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
+
## Alternate Data Structures ##
|
63
|
+
|
64
|
+
The set\_data method on a Hotwire::Response object can be called with several different data structures in order to make getting data into the response as smoothly as possible. See the documentation for Hotwire::Response.set\_data for more details.
|
65
|
+
|
62
66
|
## ActiveRecord ##
|
63
67
|
|
64
68
|
If your project includes ActiveRecord, Hotwire will automatically included an ActiveRecord mixin that allows columns to be added from a model class.
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/hotwire.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{hotwire}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Les Freeman"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-11-02}
|
13
13
|
s.description = %q{Hotwire is designed to ease the pain of creating Google Wire protocol compatible data source in Ruby.}
|
14
14
|
s.email = %q{les@codebenders.com}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -34,26 +34,113 @@ module Hotwire
|
|
34
34
|
end
|
35
35
|
alias_method :add_col, :add_column
|
36
36
|
|
37
|
-
# Adds
|
38
|
-
#
|
37
|
+
# Adds a colleciton of columns to the visualization
|
38
|
+
# +columns+ can either be an array of column definitions:
|
39
|
+
# add_columns(['string', {:id => 'Column A'}], ['number', {:id => 'Column B'}])
|
40
|
+
#
|
41
|
+
# or a sample row of data, represented as a hash keyed as column_name => value:
|
42
|
+
# add_columns({:column_a => 'a1', :column_b => 'b1})
|
43
|
+
# column_name keys are expected to be symbols(string keys do not maintain order).
|
39
44
|
def add_columns(columns)
|
40
|
-
columns.
|
45
|
+
if columns.first.is_a?(Hash)
|
46
|
+
add_columns_from_data_hash(columns)
|
47
|
+
else
|
48
|
+
add_columns_from_array(columns)
|
49
|
+
end
|
41
50
|
end
|
42
51
|
|
43
|
-
# Sets the data to be exported.
|
44
|
-
#
|
45
|
-
#
|
46
|
-
#
|
47
|
-
#
|
52
|
+
# Sets the data to be exported.
|
53
|
+
# +data+ can be a 2-dimensional array of plain data, an array of hashes that are keyed
|
54
|
+
# column_name => value, or a hash with a :columns key and a :rows key
|
55
|
+
#
|
56
|
+
# If passing a 2-dimensional array, the first index should iterate over rows,
|
57
|
+
# the second over columns. Column ordering must be the same used in +add_col+
|
58
|
+
# invokations. Anything that behaves like a 2-dimensional array and supports +each+ is
|
48
59
|
# a perfectly fine alternative.
|
60
|
+
#
|
61
|
+
# If passing an array of column_name => value hashes and no columns have been added,
|
62
|
+
# a column will automatically be added for each entry in the first row of data.
|
63
|
+
# If columns have already been added then the data will be filtered to those
|
64
|
+
# columns. column_name keys are expected to be symbols(string keys do not maintain order).
|
65
|
+
#
|
66
|
+
# If passing a hash with :columns key and a :rows key,
|
67
|
+
# :columns should be an array of column ids: ['col_a', 'col_b'...'col_N']
|
68
|
+
# :rows should be a 2-dimensional array of data: [['a1', 'b1']...['aN', 'bN']]
|
69
|
+
# Note that each row of data must be in the same order as the column id array.
|
49
70
|
def set_data(data)
|
50
|
-
|
71
|
+
if data.is_a?(Hash)
|
72
|
+
set_data_from_hash(data)
|
73
|
+
elsif data.first.is_a?(Hash)
|
74
|
+
set_data_from_array_of_hashes(data)
|
75
|
+
else
|
76
|
+
set_data_from_array(data)
|
77
|
+
end
|
51
78
|
return self
|
52
79
|
end
|
53
80
|
|
54
81
|
# Placeholder method for the subclasses to overwrite
|
55
82
|
def body
|
56
83
|
end
|
84
|
+
|
85
|
+
protected
|
86
|
+
|
87
|
+
# Adds columns to the response based on a sample row of data in the form of a hash
|
88
|
+
# keyed as column_name => value
|
89
|
+
def add_columns_from_data_hash(data)
|
90
|
+
data.first.each do |key, value|
|
91
|
+
add_column(column_type_for_value(value), :id => key.to_s, :label => key.to_s)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# Determines the appropriate Wire Protocol column type for +value+
|
96
|
+
def column_type_for_value(value)
|
97
|
+
case value.class.name
|
98
|
+
when 'BigDecimal', 'Fixnum', 'Float'
|
99
|
+
'number'
|
100
|
+
when /Time/
|
101
|
+
'datetime'
|
102
|
+
when 'Date'
|
103
|
+
'date'
|
104
|
+
when 'String'
|
105
|
+
'string'
|
106
|
+
else
|
107
|
+
'string'
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
# Adds multiple columns to the response from an array of column definitions:
|
112
|
+
# add_columns(['string', {:id => 'Column A'}], ['number', {:id => 'Column B'}])
|
113
|
+
def add_columns_from_array(columns)
|
114
|
+
columns.each { |col| add_column(*col)}
|
115
|
+
end
|
116
|
+
|
117
|
+
# Sets up the response based on a hash that has a :columns key and a :rows key.
|
118
|
+
# :columns should be an array of column ids: ['col_a', 'col_b'...'col_N']
|
119
|
+
# :rows should be a 2-dimensional array of data: [['a1', 'b1']...['aN', 'bN']]
|
120
|
+
# This method adds columns based on the first row of data and the provided
|
121
|
+
# array of column ids. Note that each row of data must be in the same
|
122
|
+
# order as the column id array.
|
123
|
+
def set_data_from_hash(data)
|
124
|
+
data[:columns].each_with_index do |column_name, index|
|
125
|
+
sample_value = data[:rows].first[index]
|
126
|
+
add_column(column_type_for_value(sample_value), :id => column_name, :label => column_name)
|
127
|
+
end
|
128
|
+
set_data_from_array(data[:rows])
|
129
|
+
end
|
130
|
+
|
131
|
+
# Sets the response data from an array of row hashes that are keyed column_name => value.
|
132
|
+
# If there are no columns setup, they are added automatically.
|
133
|
+
# Data is filtered on the columns that exist.
|
134
|
+
def set_data_from_array_of_hashes(data)
|
135
|
+
add_columns(data) if columns.empty?
|
136
|
+
set_data(data.map { |row| self.columns.map { |c| row[c[:id].to_sym] } })
|
137
|
+
end
|
138
|
+
|
139
|
+
# Sets the response data from a two dimensional array of innumerables.
|
140
|
+
def set_data_from_array(data)
|
141
|
+
@data = data
|
142
|
+
end
|
143
|
+
|
57
144
|
end
|
58
145
|
|
59
146
|
end
|
data/test/response/test_base.rb
CHANGED
@@ -39,14 +39,76 @@ class TestResponseBase < Test::Unit::TestCase
|
|
39
39
|
end
|
40
40
|
|
41
41
|
context "set_data" do
|
42
|
-
|
43
|
-
|
44
|
-
|
42
|
+
context "from an array of hashes" do
|
43
|
+
context "when columns are not set" do
|
44
|
+
setup do
|
45
|
+
@datetime = Time.utc(2010, 11, 2, 9, 35, 00)
|
46
|
+
@data = [{:string_col => 'a1', :int_col => 2, :decimal_col => 3.3, :datetime_col => @datetime}]
|
47
|
+
@response.set_data(@data)
|
48
|
+
end
|
49
|
+
should "add columns to the response" do
|
50
|
+
expected = [{:id => 'string_col', :label => "string_col", :type => 'string'},
|
51
|
+
{:id => 'int_col', :label => "int_col", :type => 'number'},
|
52
|
+
{:id => 'decimal_col', :label => "decimal_col", :type => 'number'},
|
53
|
+
{:id => 'datetime_col', :label => "datetime_col", :type => 'datetime'}]
|
54
|
+
assert_equal expected, @response.columns
|
55
|
+
end
|
56
|
+
should "set the data for the response" do
|
57
|
+
assert_equal [['a1', 2, 3.3, @datetime]], @response.data
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
context "when columns are already set" do
|
62
|
+
setup do
|
63
|
+
@data = [{:col_a => 'a1', :col_b => 'b1', :col_c => 'c1'}]
|
64
|
+
@response.add_columns([['string', {:id => 'col_c', :label => 'col_c'}],
|
65
|
+
['string', {:id => 'col_a', :label => 'col_a'}]])
|
66
|
+
@response.set_data(@data)
|
67
|
+
end
|
68
|
+
should "add columns to the response" do
|
69
|
+
expected = [{:id => 'col_c', :label => "col_c", :type => 'string'},
|
70
|
+
{:id => 'col_a', :label => "col_a", :type => 'string'}]
|
71
|
+
assert_equal expected, @response.columns
|
72
|
+
end
|
73
|
+
should "set the data for the response" do
|
74
|
+
assert_equal [['c1', 'a1']], @response.data
|
75
|
+
end
|
76
|
+
end
|
45
77
|
end
|
46
78
|
|
47
|
-
|
48
|
-
|
79
|
+
context "from a :rows, :columns hash" do
|
80
|
+
setup do
|
81
|
+
@datetime = Time.utc(2010, 11, 2, 9, 35, 00)
|
82
|
+
@data = {:columns => ["string_col", "int_col", "decimal_col", "datetime_col"],
|
83
|
+
:rows => [['a1', 2, 3.3, @datetime]]}
|
84
|
+
@response.set_data(@data)
|
85
|
+
end
|
86
|
+
|
87
|
+
should "add columns to the response" do
|
88
|
+
expected = [{:id => 'string_col', :label => "string_col", :type => 'string'},
|
89
|
+
{:id => 'int_col', :label => "int_col", :type => 'number'},
|
90
|
+
{:id => 'decimal_col', :label => "decimal_col", :type => 'number'},
|
91
|
+
{:id => 'datetime_col', :label => "datetime_col", :type => 'datetime'}]
|
92
|
+
assert_equal expected, @response.columns
|
93
|
+
end
|
94
|
+
|
95
|
+
should "set the data from the response" do
|
96
|
+
assert_equal [['a1', 2, 3.3, @datetime]], @response.data
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
context "from an array of arrays" do
|
101
|
+
setup do
|
102
|
+
@data = [['a', 'b']]
|
103
|
+
@response.set_data(@data)
|
104
|
+
end
|
105
|
+
|
106
|
+
should "set the data for the response" do
|
107
|
+
assert_equal @data, @response.data
|
108
|
+
end
|
49
109
|
end
|
110
|
+
|
111
|
+
|
50
112
|
end
|
51
113
|
|
52
114
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: hotwire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 31
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 2
|
10
|
+
version: 0.1.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Les Freeman
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-11-02 00:00:00 -07:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|