hotwire 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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