hotwire 0.1.1 → 0.1.2

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.
@@ -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
1
+ 0.1.2
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{hotwire}
8
- s.version = "0.1.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-10-25}
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 an array of columns to the visualization:
38
- # add_columns(['string', {:id => 'Column A'}], ['number', {:id => 'Column B'}])
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.each { |col| add_column(*col)}
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. +data+ should be a 2-dimensional array. The
44
- # first index should iterate over rows, the second over columns. Column
45
- # ordering must be the same used in +add_col+ invokations.
46
- #
47
- # Anything that behaves like a 2-dimensional array and supports +each+ is
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
- @data = data
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
@@ -39,14 +39,76 @@ class TestResponseBase < Test::Unit::TestCase
39
39
  end
40
40
 
41
41
  context "set_data" do
42
- setup do
43
- @data = [['a', 'b']]
44
- @response.set_data(@data)
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
- should "set the data for the response" do
48
- assert_equal @data, @response.data
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: 25
4
+ hash: 31
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
8
  - 1
9
- - 1
10
- version: 0.1.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-10-25 00:00:00 -07:00
18
+ date: 2010-11-02 00:00:00 -07:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency