hotwire 0.1.0 → 0.1.1

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/README.markdown CHANGED
@@ -44,20 +44,56 @@ The following is a basic example of use.
44
44
  ]
45
45
  respond_to do |wants|
46
46
  wants.json do
47
- if wire_request = Hotwire::Request.from_param(params)
48
- wire_response = wire_request.build_response
49
- wire_response.add_col('date', :id => 'A' , :label => 'Date').
50
- add_col('string', :id => 'B' , :label => 'Name').
51
- add_col('number', :id => 'C', :label => 'Count').
52
- set_data(data) if wire_req.valid?
53
- wire_request.body
54
- else
55
- data.to_json
47
+ if wire_request = Hotwire::Request.from_param(params)
48
+ wire_response = wire_request.build_response
49
+ wire_response.add_col('date', :id => 'A' , :label => 'Date').
50
+ add_col('string', :id => 'B' , :label => 'Name').
51
+ add_col('number', :id => 'C', :label => 'Count').
52
+ set_data(data) if wire_request.valid?
53
+ wire_response.body
54
+ else
55
+ data.to_json
56
+ end
56
57
  end
57
58
  end
58
59
  end
59
60
  end
60
61
 
62
+ ## ActiveRecord ##
63
+
64
+ If your project includes ActiveRecord, Hotwire will automatically included an ActiveRecord mixin that allows columns to be added from a model class.
65
+
66
+ Let's say you have a Person Model:
67
+
68
+ Class Person < ActiveRecord::Base
69
+ end
70
+
71
+ Then, when you have created your response object, you can add all the columns from the Person Model:
72
+
73
+ ...
74
+ wire_response.add_columns(Person)
75
+ ...
76
+
77
+ Finally, you can pass a collection of People to set_data:
78
+
79
+ ...
80
+ @people = Personal.find(:all)
81
+ wire_response.set_data(@people)
82
+ ...
83
+
84
+ You can also set the columns manually and then still use set_data with a collection. This will only set data with columns you have already added, matching the id key of the column definition to the attribute on your objects:
85
+
86
+ ...
87
+ wire_response.add_col('string', :id => 'name' , :label => 'Name').
88
+ add_col('number', :id => 'age' , :label => 'Age')
89
+ wire_response.set_data(Person.all)
90
+ ...
91
+
92
+ In that case, your wire_response.data will look like:
93
+
94
+ wire_response.data => [['Bob', 33], ['Fred', 22]]
95
+
96
+
61
97
  ## ToDo
62
98
  TODO: should be updated to handle version 0.6 of the API
63
99
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.1.1
data/hotwire.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{hotwire}
8
- s.version = "0.1.0"
8
+ s.version = "0.1.1"
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"]
@@ -28,18 +28,20 @@ Gem::Specification.new do |s|
28
28
  "lib/hotwire/base.rb",
29
29
  "lib/hotwire/request.rb",
30
30
  "lib/hotwire/response.rb",
31
+ "lib/hotwire/response/active_record_mixin.rb",
31
32
  "lib/hotwire/response/base.rb",
32
33
  "lib/hotwire/response/csv.rb",
33
34
  "lib/hotwire/response/html.rb",
34
35
  "lib/hotwire/response/invalid.rb",
35
36
  "lib/hotwire/response/json.rb",
37
+ "test/active_record_test_helper.rb",
36
38
  "test/hotwire_test.rb",
39
+ "test/response/test_active_record_mixin.rb",
37
40
  "test/response/test_base.rb",
38
41
  "test/response/test_csv.rb",
39
42
  "test/response/test_html.rb",
40
43
  "test/response/test_invalid.rb",
41
44
  "test/response/test_json.rb",
42
- "test/test_active_record_mixins.rb",
43
45
  "test/test_helper.rb",
44
46
  "test/test_request.rb",
45
47
  "test/test_response.rb"
@@ -47,16 +49,17 @@ Gem::Specification.new do |s|
47
49
  s.homepage = %q{http://github.com/lesfreeman/hotwire}
48
50
  s.rdoc_options = ["--charset=UTF-8"]
49
51
  s.require_paths = ["lib"]
50
- s.rubygems_version = %q{1.3.6}
52
+ s.rubygems_version = %q{1.3.7}
51
53
  s.summary = %q{Under the hood data transformations for the Google Wire protocol.}
52
54
  s.test_files = [
53
- "test/hotwire_test.rb",
55
+ "test/active_record_test_helper.rb",
56
+ "test/hotwire_test.rb",
57
+ "test/response/test_active_record_mixin.rb",
54
58
  "test/response/test_base.rb",
55
59
  "test/response/test_csv.rb",
56
60
  "test/response/test_html.rb",
57
61
  "test/response/test_invalid.rb",
58
62
  "test/response/test_json.rb",
59
- "test/test_active_record_mixins.rb",
60
63
  "test/test_helper.rb",
61
64
  "test/test_request.rb",
62
65
  "test/test_response.rb"
@@ -66,7 +69,7 @@ Gem::Specification.new do |s|
66
69
  current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
67
70
  s.specification_version = 3
68
71
 
69
- if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
72
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
70
73
  s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
71
74
  s.add_development_dependency(%q<redgreen>, [">= 0"])
72
75
  s.add_development_dependency(%q<mocha>, [">= 0"])
data/lib/hotwire.rb CHANGED
@@ -11,4 +11,10 @@ require 'hotwire/response/base'
11
11
  require 'hotwire/response/csv'
12
12
  require 'hotwire/response/json'
13
13
  require 'hotwire/response/html'
14
- require 'hotwire/response/invalid'
14
+ require 'hotwire/response/invalid'
15
+
16
+
17
+
18
+ if defined? ActiveRecord::Base
19
+ require 'hotwire/response/active_record_mixin.rb'
20
+ end
@@ -0,0 +1,51 @@
1
+ module Hotwire
2
+ module Response
3
+
4
+ # This mixin adds the ability to pass an ActiveRecord model to add_columns
5
+ module ActiveRecordMixin
6
+ def add_columns_with_active_record_model(args)
7
+ if args.respond_to?(:ancestors) and args.ancestors.include? ActiveRecord::Base
8
+ args = args.columns.sort_by{|c| c.name }.map do |col|
9
+ [normalize_active_record_type(col.type), {:id => col.name, :label => col.name }]
10
+ end
11
+ end
12
+ add_columns_without_active_record_model(args)
13
+
14
+ end
15
+
16
+ def set_data_with_active_record_collection(data)
17
+ data = rows_from_active_record_collection(data) if data.first.is_a?(ActiveRecord::Base)
18
+ set_data_without_active_record_collection(data)
19
+ end
20
+
21
+ def self.included(base)
22
+ base.send :alias_method_chain, :add_columns, :active_record_model
23
+ base.send :alias_method_chain, :set_data, :active_record_collection
24
+ end
25
+
26
+ private
27
+
28
+ # Converts an Array of ActiveRecord objects to an Array of data points based on columns setup for the response.
29
+ def rows_from_active_record_collection(collection)
30
+ collection.map { |obj| self.columns.map { |c| obj[c[:id]] } }
31
+ end
32
+
33
+ # Convert an ActiveRecord type string to Wire Protocol types
34
+ def normalize_active_record_type(type)
35
+ case type
36
+ when :timestamp
37
+ 'datetime'
38
+ when :string, :text
39
+ 'string'
40
+ when :decimal, :integer
41
+ 'number'
42
+ else
43
+ type.to_s
44
+ end
45
+ end
46
+
47
+ end
48
+ end
49
+ end
50
+
51
+ Hotwire::Response::Base.send :include, Hotwire::Response::ActiveRecordMixin
@@ -24,7 +24,7 @@ module Hotwire
24
24
  # be raised. +params+ is an optional map to define extra column attributes.
25
25
  # These include: +:id+, +:label+ and +:pattern+.
26
26
  def add_column(type, params=nil)
27
- raise ArgumentError.new("Invalid column type: #{type}") if !@coltypes.include?(type)
27
+ raise ArgumentError.new("Invalid column type: #{type}(#{type.class.name})") if !@coltypes.include?(type)
28
28
  params ||= {}
29
29
  params[:type] = type
30
30
 
@@ -33,6 +33,12 @@ module Hotwire
33
33
  return self
34
34
  end
35
35
  alias_method :add_col, :add_column
36
+
37
+ # Adds an array of columns to the visualization:
38
+ # add_columns(['string', {:id => 'Column A'}], ['number', {:id => 'Column B'}])
39
+ def add_columns(columns)
40
+ columns.each { |col| add_column(*col)}
41
+ end
36
42
 
37
43
  # Sets the data to be exported. +data+ should be a 2-dimensional array. The
38
44
  # first index should iterate over rows, the second over columns. Column
@@ -59,7 +59,7 @@ module Hotwire
59
59
  when "date"
60
60
  Hotwire::Response::Json::Date.new(value)
61
61
  when "datetime"
62
- Hotwire::Response::Json::Datetime.new(value)
62
+ Hotwire::Response::Json::DateTime.new(value)
63
63
  when "timeofday"
64
64
  [ value.hour, value.min, value.sec, value.usec / 1000 ]
65
65
  end
@@ -86,7 +86,7 @@ module Hotwire
86
86
  end
87
87
 
88
88
  def to_json(options=nil)
89
- "new Date(#{@date.year}, #{@date.month-1}, #{@date.day}, #{@date.hour}, #{@date.min}, #{@date.sec})"
89
+ "new Date(#{@datetime.year}, #{@datetime.month-1}, #{@datetime.day}, #{@datetime.hour}, #{@datetime.min}, #{@datetime.sec})"
90
90
  end
91
91
  end
92
92
 
@@ -0,0 +1,17 @@
1
+ require 'active_record'
2
+ ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
3
+
4
+ ActiveRecord::Schema.define(:version => 1) do
5
+ create_table :people do |t|
6
+ t.integer :id
7
+ t.string :name
8
+ t.text :bio
9
+ t.integer :age
10
+ t.decimal :weight
11
+ t.datetime :birth_date
12
+ t.boolean :tall
13
+ end
14
+ end
15
+
16
+ class Person < ActiveRecord::Base
17
+ end
@@ -0,0 +1,49 @@
1
+ require 'test_helper'
2
+ require 'active_record_test_helper'
3
+
4
+
5
+ class TestActiveRecordMixin < Test::Unit::TestCase
6
+ context "the Hotwire::Response::Base instance" do
7
+
8
+ context "created from a valid request" do
9
+ setup { @response = Hotwire::Response::Base.new(valid_request) }
10
+
11
+ context "add_columns with a Model" do
12
+ setup { @response.add_columns(Person) }
13
+
14
+ should "add columns to match the ActiveRecord object" do
15
+ expected = [{:type=>"number", :label=>"age", :id=>"age"},
16
+ {:type=>"string", :label=>"bio", :id=>"bio"},
17
+ {:type=>"datetime", :label=>"birth_date", :id=>"birth_date"},
18
+ {:type=>"number", :label=>"id", :id=>"id"},
19
+ {:type=>"string", :label=>"name", :id=>"name"},
20
+ {:type=>"boolean", :label=>"tall", :id=>"tall"},
21
+ {:type=>"number", :label=>"weight", :id=>"weight"}]
22
+
23
+ assert_equal expected, @response.columns
24
+ end
25
+ end
26
+
27
+ context "set_data with a collection" do
28
+ setup do
29
+ Person.destroy_all
30
+ @time = Time.utc(1980, 9, 15, 12, 22, 23)
31
+ @bob = Person.create(:name => "Bob", :age => 30, :bio => "A Nice Guy", :birth_date => 30.years.ago, :tall => true, :weight => 155.5)
32
+ @fred = Person.create(:name => "Fred", :age => 22, :bio => "A Nice Guy Too", :birth_date => 22.years.ago, :tall => false, :weight => 110.5)
33
+ @response.add_columns(Person)
34
+ @response.set_data(Person.all)
35
+ end
36
+
37
+ should "add rows from the collection" do
38
+ expected = [[30, "A Nice Guy", @bob.birth_date, 1, "Bob", true, @bob.weight],
39
+ [22, "A Nice Guy Too", @fred.birth_date, 2, "Fred", false, @fred.weight]]
40
+
41
+ assert_equal expected.to_s, @response.data.to_s
42
+ end
43
+
44
+ end
45
+
46
+ end
47
+
48
+ end
49
+ end
@@ -29,6 +29,15 @@ class TestResponseBase < Test::Unit::TestCase
29
29
 
30
30
  end
31
31
 
32
+ context "add_columns" do
33
+ setup { @response.add_columns([['string', {:id => 'Column A'}], ['number', {:id => 'Column B'}]]) }
34
+
35
+ should "add each column passed in" do
36
+ expected = [{:type=>"string", :id=>"Column A"}, {:type=>"number", :id=>"Column B"}]
37
+ assert_equal expected, @response.columns
38
+ end
39
+ end
40
+
32
41
  context "set_data" do
33
42
  setup do
34
43
  @data = [['a', 'b']]
metadata CHANGED
@@ -1,12 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hotwire
3
3
  version: !ruby/object:Gem::Version
4
+ hash: 25
4
5
  prerelease: false
5
6
  segments:
6
7
  - 0
7
8
  - 1
8
- - 0
9
- version: 0.1.0
9
+ - 1
10
+ version: 0.1.1
10
11
  platform: ruby
11
12
  authors:
12
13
  - Les Freeman
@@ -21,9 +22,11 @@ dependencies:
21
22
  name: thoughtbot-shoulda
22
23
  prerelease: false
23
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
24
26
  requirements:
25
27
  - - ">="
26
28
  - !ruby/object:Gem::Version
29
+ hash: 3
27
30
  segments:
28
31
  - 0
29
32
  version: "0"
@@ -33,9 +36,11 @@ dependencies:
33
36
  name: redgreen
34
37
  prerelease: false
35
38
  requirement: &id002 !ruby/object:Gem::Requirement
39
+ none: false
36
40
  requirements:
37
41
  - - ">="
38
42
  - !ruby/object:Gem::Version
43
+ hash: 3
39
44
  segments:
40
45
  - 0
41
46
  version: "0"
@@ -45,9 +50,11 @@ dependencies:
45
50
  name: mocha
46
51
  prerelease: false
47
52
  requirement: &id003 !ruby/object:Gem::Requirement
53
+ none: false
48
54
  requirements:
49
55
  - - ">="
50
56
  - !ruby/object:Gem::Version
57
+ hash: 3
51
58
  segments:
52
59
  - 0
53
60
  version: "0"
@@ -74,18 +81,20 @@ files:
74
81
  - lib/hotwire/base.rb
75
82
  - lib/hotwire/request.rb
76
83
  - lib/hotwire/response.rb
84
+ - lib/hotwire/response/active_record_mixin.rb
77
85
  - lib/hotwire/response/base.rb
78
86
  - lib/hotwire/response/csv.rb
79
87
  - lib/hotwire/response/html.rb
80
88
  - lib/hotwire/response/invalid.rb
81
89
  - lib/hotwire/response/json.rb
90
+ - test/active_record_test_helper.rb
82
91
  - test/hotwire_test.rb
92
+ - test/response/test_active_record_mixin.rb
83
93
  - test/response/test_base.rb
84
94
  - test/response/test_csv.rb
85
95
  - test/response/test_html.rb
86
96
  - test/response/test_invalid.rb
87
97
  - test/response/test_json.rb
88
- - test/test_active_record_mixins.rb
89
98
  - test/test_helper.rb
90
99
  - test/test_request.rb
91
100
  - test/test_response.rb
@@ -99,34 +108,39 @@ rdoc_options:
99
108
  require_paths:
100
109
  - lib
101
110
  required_ruby_version: !ruby/object:Gem::Requirement
111
+ none: false
102
112
  requirements:
103
113
  - - ">="
104
114
  - !ruby/object:Gem::Version
115
+ hash: 3
105
116
  segments:
106
117
  - 0
107
118
  version: "0"
108
119
  required_rubygems_version: !ruby/object:Gem::Requirement
120
+ none: false
109
121
  requirements:
110
122
  - - ">="
111
123
  - !ruby/object:Gem::Version
124
+ hash: 3
112
125
  segments:
113
126
  - 0
114
127
  version: "0"
115
128
  requirements: []
116
129
 
117
130
  rubyforge_project:
118
- rubygems_version: 1.3.6
131
+ rubygems_version: 1.3.7
119
132
  signing_key:
120
133
  specification_version: 3
121
134
  summary: Under the hood data transformations for the Google Wire protocol.
122
135
  test_files:
136
+ - test/active_record_test_helper.rb
123
137
  - test/hotwire_test.rb
138
+ - test/response/test_active_record_mixin.rb
124
139
  - test/response/test_base.rb
125
140
  - test/response/test_csv.rb
126
141
  - test/response/test_html.rb
127
142
  - test/response/test_invalid.rb
128
143
  - test/response/test_json.rb
129
- - test/test_active_record_mixins.rb
130
144
  - test/test_helper.rb
131
145
  - test/test_request.rb
132
146
  - test/test_response.rb
@@ -1,61 +0,0 @@
1
- # require 'test_helper'
2
- # require 'active_record_test_helper'
3
- #
4
- #
5
- # class TestActiveRecordMixin < Test::Unit::TestCase
6
- #
7
- # context "a Hotwire::Table instance from an ActiveRecord collection" do
8
- # setup do
9
- # Person.delete_all
10
- # Person.create(:name => "Bob", :age => 33, :bio => "A nice Guy", :birth_date => Time.utc(2010, 10, 19, 9, 38, 10))
11
- # @data = Hotwire::Table.new(Person.all)
12
- # end
13
- #
14
- # context "to_wire" do
15
- # should "return a properly formatted hash" do
16
- # expected = { "table"=> {"rows"=> [{"c"=> [{"v"=>33},
17
- # {"v"=>"A nice Guy"},
18
- # {"v"=>"Date(2010, 9, 19, 9, 38, 10)"},
19
- # {"v"=>"Bob"}]}],
20
- # "cols"=> [{"type"=>"number", "id"=>"age", "label"=>"Age"},
21
- # {"type"=>"string", "id"=>"bio", "label"=>"Bio"},
22
- # {"type"=>"datetime", "id"=>"birth_date", "label"=>"Birth date"},
23
- # {"type"=>"string", "id"=>"name", "label"=>"Name"}]}}
24
- #
25
- # assert_equal expected, @data.to_wire
26
- # end
27
- # end
28
- # end
29
- #
30
- # context "an Array of ActiveRecord objects" do
31
- # setup do
32
- # Person.delete_all
33
- # Person.create(:name => "Bob", :age => 33, :bio => "A nice Guy", :birth_date => Time.utc(2010, 10, 19, 9, 38, 10))
34
- # @people = Person.all
35
- # end
36
- #
37
- # context "to_wire" do
38
- # should "return a properly formatted hash" do
39
- # expected = { "table"=> {"rows"=> [{"c"=> [{"v"=>33},
40
- # {"v"=>"A nice Guy"},
41
- # {"v"=>"Date(2010, 9, 19, 9, 38, 10)"},
42
- # {"v"=>"Bob"}]}],
43
- # "cols"=> [{"type"=>"number", "id"=>"age", "label"=>"Age"},
44
- # {"type"=>"string", "id"=>"bio", "label"=>"Bio"},
45
- # {"type"=>"datetime", "id"=>"birth_date", "label"=>"Birth date"},
46
- # {"type"=>"string", "id"=>"name", "label"=>"Name"}]}}
47
- #
48
- # assert_equal expected, @people.to_wire
49
- # end
50
- # end
51
- # end
52
- #
53
- # context "an Array of non-ActiveRecord objects" do
54
- # should "raise an error" do
55
- # assert_raises RuntimeError do
56
- # ["string"].to_wire
57
- # end
58
- # end
59
- # end
60
- #
61
- # end