dataview 0.1.0
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 +58 -0
- data/lib/data_view.rb +158 -0
- data/lib/dataview.rb +1 -0
- data/test/tc_data_view.rb +138 -0
- data/test/ts_data_view.rb +2 -0
- metadata +45 -0
data/README
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
Data View is copyrighted free software by Brian Takita <brian.takita@gmail.com>.
|
|
2
|
+
You can redistribute it and/or modify it under either the terms of the GPL, or the conditions below:
|
|
3
|
+
|
|
4
|
+
1. You may make and give away verbatim copies of the source form of the
|
|
5
|
+
software without restriction, provided that you duplicate all of the
|
|
6
|
+
original copyright notices and associated disclaimers.
|
|
7
|
+
|
|
8
|
+
2. You may modify your copy of the software in any way, provided that
|
|
9
|
+
you do at least ONE of the following:
|
|
10
|
+
|
|
11
|
+
a) place your modifications in the Public Domain or otherwise
|
|
12
|
+
make them Freely Available, such as by posting said
|
|
13
|
+
modifications to Usenet or an equivalent medium, or by allowing
|
|
14
|
+
the author to include your modifications in the software.
|
|
15
|
+
|
|
16
|
+
b) use the modified software only within your corporation or
|
|
17
|
+
organization.
|
|
18
|
+
|
|
19
|
+
c) rename any non-standard executables so the names do not conflict
|
|
20
|
+
with standard executables, which must also be provided.
|
|
21
|
+
|
|
22
|
+
d) make other distribution arrangements with the author.
|
|
23
|
+
|
|
24
|
+
3. You may distribute the software in object code or executable
|
|
25
|
+
form, provided that you do at least ONE of the following:
|
|
26
|
+
|
|
27
|
+
a) distribute the executables and library files of the software,
|
|
28
|
+
together with instructions (in the manual page or equivalent)
|
|
29
|
+
on where to get the original distribution.
|
|
30
|
+
|
|
31
|
+
b) accompany the distribution with the machine-readable source of
|
|
32
|
+
the software.
|
|
33
|
+
|
|
34
|
+
c) give non-standard executables non-standard names, with
|
|
35
|
+
instructions on where to get the original software distribution.
|
|
36
|
+
|
|
37
|
+
d) make other distribution arrangements with the author.
|
|
38
|
+
|
|
39
|
+
4. You may modify and include the part of the software into any other
|
|
40
|
+
software (possibly commercial). But some files in the distribution
|
|
41
|
+
are not written by the author, so that they are not under this terms.
|
|
42
|
+
|
|
43
|
+
They are gc.c(partly), utils.c(partly), regex.[ch], st.[ch] and some
|
|
44
|
+
files under the ./missing directory. See each file for the copying
|
|
45
|
+
condition.
|
|
46
|
+
|
|
47
|
+
5. The scripts and library files supplied as input to or produced as
|
|
48
|
+
output from the software do not automatically fall under the
|
|
49
|
+
copyright of the software, but belong to whomever generated them,
|
|
50
|
+
and may be sold commercially, and may be aggregated with this
|
|
51
|
+
software.
|
|
52
|
+
|
|
53
|
+
6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
|
54
|
+
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
|
55
|
+
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
|
56
|
+
PURPOSE.
|
|
57
|
+
|
|
58
|
+
|
data/lib/data_view.rb
ADDED
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
module DataView
|
|
2
|
+
|
|
3
|
+
# DataView is intended to reduce coupling between the Controller and View layers in a MVC application. The Controller can send a DataView to the View layer. The View layer does not need to have access to the Model.
|
|
4
|
+
class DataView
|
|
5
|
+
class Row
|
|
6
|
+
public
|
|
7
|
+
include Enumerable
|
|
8
|
+
attr_accessor :data_view
|
|
9
|
+
def initialize(data_view, values = [])
|
|
10
|
+
@data_view = data_view
|
|
11
|
+
@values = values
|
|
12
|
+
end
|
|
13
|
+
def [](key)
|
|
14
|
+
return @values[get_index(key)]
|
|
15
|
+
end
|
|
16
|
+
def []=(key, value)
|
|
17
|
+
@values[get_index(key)] = value
|
|
18
|
+
end
|
|
19
|
+
def each
|
|
20
|
+
@values.each_with_index do |v, i|
|
|
21
|
+
yield(data_view.fields[i], v)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
def length
|
|
25
|
+
@values.length
|
|
26
|
+
end
|
|
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
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
public
|
|
35
|
+
include Enumerable
|
|
36
|
+
attr_reader :fields, :titles, :delegates
|
|
37
|
+
# Initializes the DataView.
|
|
38
|
+
# ===Model
|
|
39
|
+
# 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:
|
|
48
|
+
# * :sender - The DataView sending the call
|
|
49
|
+
# * :row_index - The Index of the current row.
|
|
50
|
+
# * :column_index - The Index of the current column.
|
|
51
|
+
# * :field - The field of the current value.
|
|
52
|
+
# ====:value_transforms
|
|
53
|
+
# A Hash of the delegates 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:
|
|
54
|
+
# * :sender - The DataView sending the call
|
|
55
|
+
# * :row_index - The Index of the current row.
|
|
56
|
+
# * :column_index - The Index of the current column.
|
|
57
|
+
# * :value - The current value.
|
|
58
|
+
# * :field - The field of the current value.
|
|
59
|
+
def initialize(model, params = {})
|
|
60
|
+
@model = model.respond_to?(:each_index) ? model : [model]
|
|
61
|
+
|
|
62
|
+
# @fields is an ordered array of the fields that will be shown
|
|
63
|
+
@fields = get_param_value(params, :fields)
|
|
64
|
+
@fields = Array.new() if @fields == nil
|
|
65
|
+
|
|
66
|
+
# @titles is a hash with the field as the key and the title as the value
|
|
67
|
+
@titles = get_param_value(params, :titles)
|
|
68
|
+
@titles = Hash.new() if @titles == nil
|
|
69
|
+
|
|
70
|
+
# @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.
|
|
71
|
+
@values = get_param_value(params, :values)
|
|
72
|
+
@values = Hash.new() if @values == nil
|
|
73
|
+
|
|
74
|
+
# @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
|
|
75
|
+
# The Proc that is the value must accept a hash that has the following keys:
|
|
76
|
+
# :sender, :row_index, :column_index, :value, :field
|
|
77
|
+
value_transforms = get_param_value(params, :value_transforms)
|
|
78
|
+
value_transforms = Hash.new() if value_transforms == nil
|
|
79
|
+
@value_transforms = format_value_transforms(value_transforms)
|
|
80
|
+
end
|
|
81
|
+
# Gets a particular row of the view.
|
|
82
|
+
def [](index)
|
|
83
|
+
get_view_row(index)
|
|
84
|
+
end
|
|
85
|
+
# The number of rows in the result.
|
|
86
|
+
def length
|
|
87
|
+
@model.length
|
|
88
|
+
end
|
|
89
|
+
# Iterates through each row of the view.
|
|
90
|
+
def each
|
|
91
|
+
@model.each_index do |row_index|
|
|
92
|
+
yield(get_view_row(row_index))
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
# Iterates through each title of the fields.
|
|
96
|
+
def each_title
|
|
97
|
+
@fields.each do |field|
|
|
98
|
+
if @titles.include?(field)
|
|
99
|
+
yield(field, @titles[field])
|
|
100
|
+
else
|
|
101
|
+
yield(field, nil)
|
|
102
|
+
end
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
# Iterates through each title of the fields with the index.
|
|
106
|
+
def each_title_with_index
|
|
107
|
+
i = 0
|
|
108
|
+
each_title do |f, t|
|
|
109
|
+
yield(f, t, i)
|
|
110
|
+
i = i + 1
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
private
|
|
114
|
+
def get_view_row(row_index)
|
|
115
|
+
model_row = @model[row_index]
|
|
116
|
+
view_row_values = []
|
|
117
|
+
@fields.each_with_index do |field, field_index|
|
|
118
|
+
if @values.include?(field)
|
|
119
|
+
actual_value = @values[field].call(@model, row_index, field)
|
|
120
|
+
else
|
|
121
|
+
actual_value = model_row[field]
|
|
122
|
+
end
|
|
123
|
+
view_value = actual_value
|
|
124
|
+
|
|
125
|
+
if @value_transforms.include?(field)
|
|
126
|
+
delegate_value = actual_value
|
|
127
|
+
@value_transforms[field].each do |delegate|
|
|
128
|
+
delegate_params = {
|
|
129
|
+
:sender => self,
|
|
130
|
+
:row_index => row_index,
|
|
131
|
+
:column_index => field_index,
|
|
132
|
+
:value => delegate_value,
|
|
133
|
+
:field => field
|
|
134
|
+
}
|
|
135
|
+
delegate_value = delegate.call(delegate_params)
|
|
136
|
+
end
|
|
137
|
+
view_value = delegate_value
|
|
138
|
+
end
|
|
139
|
+
view_row_values << view_value
|
|
140
|
+
end
|
|
141
|
+
Row.new(self, view_row_values)
|
|
142
|
+
end
|
|
143
|
+
def get_param_value(param, key)
|
|
144
|
+
return nil if param == nil
|
|
145
|
+
return param[key]
|
|
146
|
+
end
|
|
147
|
+
def format_value_transforms(delegates)
|
|
148
|
+
delegates.each do |k, *items|
|
|
149
|
+
delegates[k] = items.flatten
|
|
150
|
+
delegates[k].each do |d|
|
|
151
|
+
raise ":delegate must respond to call" unless d.respond_to?(:call)
|
|
152
|
+
end
|
|
153
|
+
end
|
|
154
|
+
delegates
|
|
155
|
+
end
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
end
|
data/lib/dataview.rb
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
require 'data_view'
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
this_dir = File.dirname(__FILE__)
|
|
2
|
+
require this_dir << '/../lib/data_view'
|
|
3
|
+
require 'test/unit'
|
|
4
|
+
|
|
5
|
+
class DataViewTest < Test::Unit::TestCase
|
|
6
|
+
include DataView
|
|
7
|
+
public
|
|
8
|
+
def test_brackets
|
|
9
|
+
do_test_brackets(mock_model)
|
|
10
|
+
do_test_brackets(singular_mock_model)
|
|
11
|
+
end
|
|
12
|
+
def test_each
|
|
13
|
+
do_test_each(mock_model)
|
|
14
|
+
do_test_each(singular_mock_model)
|
|
15
|
+
end
|
|
16
|
+
def test_each_title
|
|
17
|
+
do_test_each_title(mock_model)
|
|
18
|
+
do_test_each_title(singular_mock_model)
|
|
19
|
+
end
|
|
20
|
+
def test_each_title_with_index
|
|
21
|
+
do_test_each_title_with_index(mock_model)
|
|
22
|
+
do_test_each_title_with_index(singular_mock_model)
|
|
23
|
+
end
|
|
24
|
+
def test_length
|
|
25
|
+
assert_equal(mock_model.length, get_data_view(mock_model).length)
|
|
26
|
+
assert_equal(1, get_data_view(singular_mock_model).length)
|
|
27
|
+
end
|
|
28
|
+
private
|
|
29
|
+
def do_test_brackets(model)
|
|
30
|
+
data_view = get_data_view(model)
|
|
31
|
+
|
|
32
|
+
test_model = model.respond_to?(:each_index) ? model : [model]
|
|
33
|
+
test_model.each_with_index do |r, i|
|
|
34
|
+
fields.each_with_index do |f, j|
|
|
35
|
+
v = (f == :model_value_field) ? get_model_value(model, i, f) : r[f]
|
|
36
|
+
assert_equal(expected_altered_value(v), data_view[i][f])
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
def do_test_each(model)
|
|
41
|
+
data_view = get_data_view(model)
|
|
42
|
+
data_view.each_with_index do |row, i|
|
|
43
|
+
expected_row = model.respond_to?(:each_index) ? model[i] : model
|
|
44
|
+
assert_equal(expected_row.length, row.to_a.length)
|
|
45
|
+
|
|
46
|
+
expected_row.each do |k, expected_value|
|
|
47
|
+
expected_value = get_model_value(model, i, k) if k == :model_value_field
|
|
48
|
+
assert_equal(expected_altered_value(expected_value), row[k])
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
def do_test_each_title(model)
|
|
53
|
+
data_view = get_data_view(model)
|
|
54
|
+
i = 0
|
|
55
|
+
data_view.each_title do |f, t|
|
|
56
|
+
assert_equal(titles[f], t)
|
|
57
|
+
i = i + 1
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
def do_test_each_title_with_index(model)
|
|
61
|
+
data_view = get_data_view(model)
|
|
62
|
+
ei = 0
|
|
63
|
+
data_view.each_title_with_index do |f, t, i|
|
|
64
|
+
assert_equal(titles[fields[ei]], t)
|
|
65
|
+
assert_equal(ei, i)
|
|
66
|
+
ei = ei + 1
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
def expected_altered_value(v)
|
|
70
|
+
"altered " << v
|
|
71
|
+
end
|
|
72
|
+
def get_data_view(model)
|
|
73
|
+
DataView.new(
|
|
74
|
+
model,
|
|
75
|
+
:fields => fields,
|
|
76
|
+
:titles => titles,
|
|
77
|
+
:values => values,
|
|
78
|
+
:value_transforms => value_transforms
|
|
79
|
+
)
|
|
80
|
+
end
|
|
81
|
+
def get_model_value_method
|
|
82
|
+
return @get_model_value_method if defined?(@get_model_value_method)
|
|
83
|
+
@get_model_value_method = method(:get_model_value)
|
|
84
|
+
end
|
|
85
|
+
def get_model_value(model, row_index, field)
|
|
86
|
+
row_index.to_s << ' : Custom ' << field.to_s
|
|
87
|
+
end
|
|
88
|
+
def fields
|
|
89
|
+
return @fields if defined?(@fields)
|
|
90
|
+
@fields = [:model_value_field , :field1, :field2, :field3]
|
|
91
|
+
end
|
|
92
|
+
def titles
|
|
93
|
+
return @titles if defined?(@titles)
|
|
94
|
+
t = Hash.new()
|
|
95
|
+
fields.each do |f|
|
|
96
|
+
t[f] = f.to_s << ' Title'
|
|
97
|
+
end
|
|
98
|
+
@titles = t
|
|
99
|
+
end
|
|
100
|
+
def singular_mock_model
|
|
101
|
+
return @singular_mock_model if defined?(@singular_mock_model)
|
|
102
|
+
@singular_mock_model = get_mock_model_row(0)
|
|
103
|
+
end
|
|
104
|
+
def mock_model
|
|
105
|
+
return @mock_model if defined?(@mock_model)
|
|
106
|
+
m = Array.new
|
|
107
|
+
(0..2).each do |i|
|
|
108
|
+
row = get_mock_model_row(i)
|
|
109
|
+
m << row
|
|
110
|
+
end
|
|
111
|
+
@mock_model = m
|
|
112
|
+
end
|
|
113
|
+
def get_mock_model_row(i)
|
|
114
|
+
row = Hash.new
|
|
115
|
+
fields.each do |f|
|
|
116
|
+
next if f.respond_to?(:call)
|
|
117
|
+
row[f] = i.to_s << ' : ' << f.to_s
|
|
118
|
+
end
|
|
119
|
+
row
|
|
120
|
+
end
|
|
121
|
+
def values
|
|
122
|
+
return @values if defined?(@values)
|
|
123
|
+
v = Hash.new
|
|
124
|
+
v[:model_value_field] = get_model_value_method
|
|
125
|
+
@values = v
|
|
126
|
+
end
|
|
127
|
+
def value_transforms
|
|
128
|
+
return @value_transforms if defined?(@value_transforms)
|
|
129
|
+
t = Hash.new()
|
|
130
|
+
fields.each do |f|
|
|
131
|
+
t[f] = lambda { |h|
|
|
132
|
+
'altered ' << h[:value].to_s
|
|
133
|
+
}
|
|
134
|
+
end
|
|
135
|
+
@value_transforms = t
|
|
136
|
+
end
|
|
137
|
+
end
|
|
138
|
+
|
metadata
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
rubygems_version: 0.8.11
|
|
3
|
+
specification_version: 1
|
|
4
|
+
name: dataview
|
|
5
|
+
version: !ruby/object:Gem::Version
|
|
6
|
+
version: 0.1.0
|
|
7
|
+
date: 2005-07-25 00:00:00 -07:00
|
|
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
|
+
require_paths:
|
|
10
|
+
- lib
|
|
11
|
+
email: brian.takita@gmail.com
|
|
12
|
+
homepage: http://DataView.rubyforge.org
|
|
13
|
+
rubyforge_project:
|
|
14
|
+
description:
|
|
15
|
+
autorequire:
|
|
16
|
+
default_executable:
|
|
17
|
+
bindir: bin
|
|
18
|
+
has_rdoc: true
|
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
|
20
|
+
requirements:
|
|
21
|
+
-
|
|
22
|
+
- ">"
|
|
23
|
+
- !ruby/object:Gem::Version
|
|
24
|
+
version: 0.0.0
|
|
25
|
+
version:
|
|
26
|
+
platform: ruby
|
|
27
|
+
signing_key:
|
|
28
|
+
cert_chain:
|
|
29
|
+
authors:
|
|
30
|
+
- Brian Takita
|
|
31
|
+
files:
|
|
32
|
+
- test/tc_data_view.rb
|
|
33
|
+
- test/ts_data_view.rb
|
|
34
|
+
- lib/dataview.rb
|
|
35
|
+
- lib/data_view.rb
|
|
36
|
+
- README
|
|
37
|
+
test_files:
|
|
38
|
+
- test/ts_data_view.rb
|
|
39
|
+
rdoc_options: []
|
|
40
|
+
extra_rdoc_files:
|
|
41
|
+
- README
|
|
42
|
+
executables: []
|
|
43
|
+
extensions: []
|
|
44
|
+
requirements: []
|
|
45
|
+
dependencies: []
|