dataview 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (3) hide show
  1. data/lib/data_view.rb +73 -94
  2. data/test/tc_data_view.rb +44 -44
  3. metadata +2 -2
data/lib/data_view.rb CHANGED
@@ -6,78 +6,67 @@ class DataView
6
6
  public
7
7
  include Enumerable
8
8
  attr_accessor :data_view
9
- def initialize(data_view, values = [])
9
+ def initialize(data_view, values = {})
10
10
  @data_view = data_view
11
11
  @values = values
12
12
  end
13
13
  def [](key)
14
- return @values[get_index(key)]
14
+ return @values[get_key(key)]
15
15
  end
16
16
  def []=(key, value)
17
- @values[get_index(key)] = value
17
+ @values[get_key(key)] = value
18
18
  end
19
19
  def each
20
- @values.each_with_index do |v, i|
21
- yield(data_view.fields[i], v)
20
+ data_view.columns.each_with_index do |c, i|
21
+ yield(c, @values[c])
22
22
  end
23
23
  end
24
24
  def length
25
25
  @values.length
26
26
  end
27
27
  private
28
- def get_index(key)
29
- return data_view.fields.index(key) if data_view.fields.include?(key)
30
- raise 'key must either be an array index integer or a field key' unless key.respond_to?(:to_i)
31
- return key
28
+ def get_key(key)
29
+ return key if data_view.columns.include?(key)
30
+ col = data_view.columns.find {|c| c[:field] == key}
31
+ return col unless col == nil
32
+ return data_view.columns[key.to_i] if key.respond_to?(:to_i)
33
+ raise "The column #{key} does not exist in this row"
32
34
  end
33
35
  end
34
36
  public
35
37
  include Enumerable
36
- attr_reader :fields, :titles, :values, :value_transforms
38
+ attr_reader :columns, :rows
37
39
  # Initializes the DataView.
38
40
  # ===Model
39
41
  # The DataView supports a model that contains an array of hashes. The keys in these hashes much be symbols of the field names. This is based off of the ActiveRecord interface.
40
- # ===Params
41
- # Params is a symbol keyed Hash of parameters to be passed.
42
- # ====:fields
43
- # An array of the fields, on order, that will be used from the model. A field value should be a Symbol or a Proc that accepts the @model and row_index and returns the value to access the value.
44
- # ====:titles
45
- # A Hash of the titles for the fields. The field symbol is the key, and the title is the value.
46
- # ====:values
47
- # A hash of Procs that get nondefault values of a field in a particular row. By default, the value is taken by looking at the field in the model. The Proc must accept a Hash of parameters and return the transformed value. The Hash contains the following keys:
42
+ # ===Columns
43
+ # An Array of Hashes that contain data about the columns and how the columns will be handled. The column order in the each method is the same as the array order.
44
+ # Each Hash contains the following keys:
45
+ # ====:field
46
+ # (Required) The database field should be a Symbol or String of the field that is called.
47
+ # ====:title
48
+ # The title of the column. If one is not given, the field value is used.
49
+ # ====:value
50
+ # The value of the particular cell. If a value is not given, the value of the database field in the model is used. If a Symbol or String is given and the model contains a field with that name, then the model value is returned. If the Symbol or string is not a field in the model, the value parameter is returned.
51
+ # If a Proc is given, the return value of the Proc is used. The Proc must accept a Hash of parameters and return the transformed value. The Hash contains the following keys:
48
52
  # * :sender - The DataView sending the call
49
53
  # * :model - The Model of the DataView
50
54
  # * :row_index - The Index of the current row.
51
55
  # * :column_index - The Index of the current column.
52
- # * :field - The field of the current value.
56
+ # * :column - The column of the current value.
53
57
  # ====:value_transforms
54
- # A Hash of the value_transforms that will process the values. The field symbol is the key, and the Proc or array of Procs to transform the value. The Proc must accept a Hash of parameters and return the transformed value. The Hash contains the following keys:
58
+ # An Array of Procs that act as event sinks to transform the value into the desired view. The transforms occur in the order of the Array. Each Proc must accept a Hash of parameters and return the transformed value. The Hash contains the following keys:
55
59
  # * :sender - The DataView sending the call
56
60
  # * :row_index - The Index of the current row.
57
61
  # * :column_index - The Index of the current column.
58
62
  # * :value - The current value.
59
- # * :field - The field of the current value.
60
- def initialize(model, params = {})
63
+ # * :column - The column of the current value.
64
+ def initialize(model, columns = [])
65
+ raise 'columns cannot be nil' if columns == nil
61
66
  @model = model.respond_to?(:each_index) ? model : [model]
62
67
 
63
- # @fields is an ordered array of the fields that will be shown
64
- @fields = get_param_value(params, :fields)
65
- @fields = Array.new() if @fields == nil
66
-
67
- # @titles is a hash with the field as the key and the title as the value
68
- @titles = get_param_value(params, :titles)
69
- @titles = Hash.new() if @titles == nil
70
-
71
- # @values is a hash of Procs that get nondefault values of a field in a particular row. By default, the value is taken by looking at the field in the model.
72
- @values = get_param_value(params, :values)
73
- @values = Hash.new() if @values == nil
74
-
75
- # @value_transforms is a hash with the field as the key and a Proc or array of procs that transforms the value into the proper format as the value
76
- # The Proc that is the value must accept a hash that has the following keys:
77
- # :sender, :row_index, :column_index, :value, :field
78
- value_transforms = get_param_value(params, :value_transforms)
79
- value_transforms = Hash.new() if value_transforms == nil
80
- @value_transforms = format_value_transforms(value_transforms)
68
+ # @columns is an ordered array of the columns that will be shown
69
+ @columns = columns
81
70
  end
82
71
  # Gets a particular row of the view.
83
72
  def [](index)
@@ -93,17 +82,15 @@ class DataView
93
82
  yield(get_view_row(row_index))
94
83
  end
95
84
  end
96
- # Iterates through each title of the fields.
85
+ # Iterates through each title of the columns.
97
86
  def each_title
98
- @fields.each do |field|
99
- if @titles.include?(field)
100
- yield(field, @titles[field])
101
- else
102
- yield(field, nil)
103
- end
87
+ @columns.each do |column|
88
+ column_title = column[:title]
89
+ title = (column_title == nil) ? column[:field] : column[:title]
90
+ yield(column, title)
104
91
  end
105
92
  end
106
- # Iterates through each title of the fields with the index.
93
+ # Iterates through each title of the columns with the index.
107
94
  def each_title_with_index
108
95
  i = 0
109
96
  each_title do |f, t|
@@ -114,57 +101,49 @@ class DataView
114
101
  private
115
102
  def get_view_row(row_index)
116
103
  model_row = @model[row_index]
117
- view_row_values = []
118
- @fields.each_with_index do |field, field_index|
119
- if @values.include?(field)
120
- actual_value = @values[field].call(
121
- {
122
- :sender => self,
123
- :model => @model,
124
- :row_index => row_index,
125
- :column_index => field_index,
126
- :field => field
127
- }
128
- )
129
- else
130
- actual_value = model_row[field]
131
- end
132
- view_value = actual_value
133
-
134
- if @value_transforms.include?(field)
135
- transform_value = actual_value
136
-
137
- transforms = @value_transforms[field]
138
- transforms = [transforms] unless transforms.respond_to?(:each)
139
- transforms.each do |transform|
140
- next unless transform
141
- transform_params = {
142
- :sender => self,
143
- :row_index => row_index,
144
- :column_index => field_index,
145
- :value => transform_value,
146
- :field => field
147
- }
148
- transform_value = transform.call(transform_params)
149
- end
150
- view_value = transform_value
151
- end
152
- view_row_values << view_value
104
+ view_row_values = {}
105
+ @columns.each_with_index do |column, column_index|
106
+ value = get_raw_value(model_row, column, row_index, column_index)
107
+ value = get_transformed_value(value, column, row_index, column_index)
108
+ view_row_values[column] = value
153
109
  end
154
110
  Row.new(self, view_row_values)
155
111
  end
156
- def get_param_value(param, key)
157
- return nil if param == nil
158
- return param[key]
112
+ def get_raw_value(model_row, col, row_index, column_index)
113
+ value_param = col[:value]
114
+ return model_row[col[:field]] if value_param == nil
115
+
116
+ return @columns[value_param] if @columns.any? {|f| f[:field] == value_param}
117
+
118
+ return value_param.call(
119
+ {
120
+ :sender => self,
121
+ :model => @model,
122
+ :row_index => row_index,
123
+ :column_index => column_index,
124
+ :column => col
125
+ }
126
+ ) if value_param.respond_to?(:call)
127
+
128
+ return value_param
159
129
  end
160
- def format_value_transforms(value_transforms)
161
- value_transforms.each do |k, *items|
162
- value_transforms[k] = items.flatten
163
- value_transforms[k].each do |d|
164
- raise ":delegate must respond to call" unless d.respond_to?(:call)
165
- end
130
+ def get_transformed_value(value, column, row_index, column_index)
131
+ transforms = column[:value_transforms]
132
+ return value if transforms == nil
133
+
134
+ transforms = [transforms] unless transforms.respond_to?(:each)
135
+ transforms.each do |transform|
136
+ next unless transform
137
+ transform_params = {
138
+ :sender => self,
139
+ :row_index => row_index,
140
+ :column_index => column_index,
141
+ :value => value,
142
+ :column => column
143
+ }
144
+ value = transform.call(transform_params)
166
145
  end
167
- value_transforms
146
+ value
168
147
  end
169
148
  end
170
149
 
data/test/tc_data_view.rb CHANGED
@@ -27,15 +27,17 @@ class DataViewTest < Test::Unit::TestCase
27
27
  end
28
28
  def test_value_transforms_accessor
29
29
  data_view = get_data_view(mock_model)
30
- data_view.value_transforms[:field1] = nil
31
- assert_equal(mock_model[0][:field1], data_view[0][:field1])
30
+ col = data_view.columns.find {|col| col[:field] == :field1}
31
+ col[:value_transforms] = nil
32
+ field = col[:field]
33
+ assert_equal(mock_model[0][field], data_view[0][:field1])
32
34
 
33
35
  test_transform = lambda { |h|
34
36
  'test ' << h[:value].to_s
35
37
  }
36
- data_view.value_transforms[:field1] = test_transform
38
+ col[:value_transforms] = test_transform
37
39
 
38
- expected_transform_value = test_transform.call({:value => mock_model[0][:field1]})
40
+ expected_transform_value = test_transform.call({:value => mock_model[0][field]})
39
41
  assert_equal(expected_transform_value, data_view[0][:field1])
40
42
  end
41
43
  private
@@ -44,11 +46,12 @@ class DataViewTest < Test::Unit::TestCase
44
46
 
45
47
  test_model = model.respond_to?(:each_index) ? model : [model]
46
48
  test_model.each_with_index do |r, i|
47
- fields.each_with_index do |f, j|
49
+ columns.each_with_index do |col, j|
50
+ f = col[:field]
48
51
  if f != :model_value_field
49
52
  v = r[f]
50
53
  else
51
- v = get_model_value({:sender => self, :model => model, :row_index => i, :field => f})
54
+ v = get_model_value({:sender => self, :model => model, :row_index => i, :column => col})
52
55
  end
53
56
  assert_equal(expected_altered_value(v), data_view[i][f])
54
57
  end
@@ -60,11 +63,12 @@ class DataViewTest < Test::Unit::TestCase
60
63
  expected_row = model.respond_to?(:each_index) ? model[i] : model
61
64
  assert_equal(expected_row.length, row.to_a.length)
62
65
 
63
- expected_row.each do |k, expected_value|
64
- if k == :model_value_field
65
- expected_value = get_model_value({:sender => self, :model => model, :row_index => i, :field => k})
66
+ expected_row.each do |f, expected_value|
67
+ col = data_view.columns.find{|col| col[:field] == f}
68
+ if f == :model_value_field
69
+ expected_value = get_model_value({:sender => self, :model => model, :row_index => i, :column => col})
66
70
  end
67
- assert_equal(expected_altered_value(expected_value), row[k])
71
+ assert_equal(expected_altered_value(expected_value), row[f])
68
72
  end
69
73
  end
70
74
  end
@@ -72,7 +76,7 @@ class DataViewTest < Test::Unit::TestCase
72
76
  data_view = get_data_view(model)
73
77
  i = 0
74
78
  data_view.each_title do |f, t|
75
- assert_equal(titles[f], t)
79
+ assert_equal(f[:title], t)
76
80
  i = i + 1
77
81
  end
78
82
  end
@@ -80,7 +84,7 @@ class DataViewTest < Test::Unit::TestCase
80
84
  data_view = get_data_view(model)
81
85
  ei = 0
82
86
  data_view.each_title_with_index do |f, t, i|
83
- assert_equal(titles[fields[ei]], t)
87
+ assert_equal(f[:title], t)
84
88
  assert_equal(ei, i)
85
89
  ei = ei + 1
86
90
  end
@@ -89,13 +93,7 @@ class DataViewTest < Test::Unit::TestCase
89
93
  "altered " << v
90
94
  end
91
95
  def get_data_view(model)
92
- DataView.new(
93
- model,
94
- :fields => fields,
95
- :titles => titles,
96
- :values => values,
97
- :value_transforms => value_transforms
98
- )
96
+ DataView.new(model, columns)
99
97
  end
100
98
  def get_model_value_method
101
99
  return @get_model_value_method if defined?(@get_model_value_method)
@@ -106,7 +104,7 @@ class DataViewTest < Test::Unit::TestCase
106
104
  test_model = params[:model]
107
105
  test_row_index = params[:row_index]
108
106
  test_column_index = params[:column_index]
109
- test_field = params[:field]
107
+ test_column = params[:column]
110
108
 
111
109
  unless test_sender == self
112
110
  assert_equal(DataView, test_sender.class)
@@ -114,23 +112,29 @@ class DataViewTest < Test::Unit::TestCase
114
112
  assert_equal(singular_mock_model, test_model[0])
115
113
  end
116
114
  assert((0..2).include?(test_row_index))
117
- assert(fields.include?(test_field))
118
- fi = fields.index(test_field)
115
+ assert(columns.include?(test_column))
116
+ fi = columns.index(test_column)
119
117
  assert_equal(fi, test_column_index)
120
118
  end
121
- test_row_index.to_s << ' : Custom ' << test_field.to_s
119
+ test_row_index.to_s << ' : Custom ' << test_column[:field].to_s
122
120
  end
123
- def fields
124
- return @fields if defined?(@fields)
125
- @fields = [:model_value_field , :field1, :field2, :field3]
126
- end
127
- def titles
128
- return @titles if defined?(@titles)
129
- t = Hash.new()
130
- fields.each do |f|
131
- t[f] = f.to_s << ' Title'
121
+ def columns
122
+ return @columns if defined?(@columns)
123
+
124
+ columns = []
125
+ [:model_value_field, :field1, :field2, :field3].each do |f|
126
+ column = Hash.new
127
+ column[:field] = f
128
+ column[:title] = get_title(f)
129
+ column[:value] = get_model_value_method if f == :model_value_field
130
+ column[:value_transforms] = value_transform
131
+ columns.push(column)
132
132
  end
133
- @titles = t
133
+
134
+ @columns = columns
135
+ end
136
+ def get_title(field)
137
+ "#{field.to_s} Title"
134
138
  end
135
139
  def singular_mock_model
136
140
  return @singular_mock_model if defined?(@singular_mock_model)
@@ -147,9 +151,9 @@ class DataViewTest < Test::Unit::TestCase
147
151
  end
148
152
  def get_mock_model_row(i)
149
153
  row = Hash.new
150
- fields.each do |f|
151
- next if f.respond_to?(:call)
152
- row[f] = i.to_s << ' : ' << f.to_s
154
+ columns.each do |f|
155
+ field = f[:field]
156
+ row[field] = i.to_s << ' : ' << field.to_s
153
157
  end
154
158
  row
155
159
  end
@@ -159,15 +163,11 @@ class DataViewTest < Test::Unit::TestCase
159
163
  v[:model_value_field] = get_model_value_method
160
164
  @values = v
161
165
  end
162
- def value_transforms
163
- return @value_transforms if defined?(@value_transforms)
164
- t = Hash.new()
165
- fields.each do |f|
166
- t[f] = lambda { |h|
167
- 'altered ' << h[:value].to_s
168
- }
166
+ def value_transform
167
+ return @value_transform if defined?(@value_transform)
168
+ @value_transform = lambda do |h|
169
+ 'altered ' << h[:value].to_s
169
170
  end
170
- @value_transforms = t
171
171
  end
172
172
  end
173
173
 
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.11
3
3
  specification_version: 1
4
4
  name: dataview
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.1.1
7
- date: 2005-07-25 00:00:00 -07:00
6
+ version: 0.2.0
7
+ date: 2005-07-26 00:00:00 -07:00
8
8
  summary: Data View is a library that creates a view of a data model. The view can transform the data of the data model without changing the data. Supports ActiveRecord models and other data models that have a similar interface.
9
9
  require_paths:
10
10
  - lib