unidata 0.0.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/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Jeremy Israelsen, TotalCareAuto
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,99 @@
1
+ UniData ORM
2
+ ===========
3
+
4
+ A simple ORM for Rocket's UniData database.
5
+
6
+ Installation
7
+ ------------
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'unidata'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install unidata
20
+
21
+ Usage
22
+ -----
23
+
24
+ Model definition:
25
+
26
+ ```ruby
27
+ class Product < Unidata::Model
28
+ self.filename = 'PRODUCT'
29
+
30
+ field 1, :name, String
31
+ field 2, :description # type is optional (defaults to String)
32
+ field 3, :cost, Float
33
+ field 4, :available_on, Date
34
+ end
35
+ ```
36
+
37
+ Creating records:
38
+
39
+ ```ruby
40
+ thingamajig = Product.new(
41
+ :id => 12345,
42
+ :name =>'Thingamajig',
43
+ :cost => 125.99,
44
+ :available => Date.today
45
+ )
46
+ thingamajig.save
47
+
48
+ whatsit = Product.new
49
+ whatsit.id = 12346
50
+ whatsit.name = 'Whatsit'
51
+ whatsit.cost = 999.99
52
+ whatsit.available = Date.today
53
+ whatsit.save
54
+ ```
55
+
56
+ Record retrieval:
57
+
58
+ ```ruby
59
+ product = Product.find(12345)
60
+ ```
61
+
62
+ Checking if a record exists:
63
+
64
+ ```ruby
65
+ Product.exists?(12345)
66
+ ```
67
+
68
+ Contributing
69
+ ------------
70
+
71
+ Pull requests are welcome. Just make sure to include tests!
72
+
73
+ To run tests, install some dependencies:
74
+
75
+ ```bash
76
+ bundle install
77
+ ```
78
+
79
+ Then, run tests with:
80
+
81
+ ```bash
82
+ rake spec
83
+ ```
84
+
85
+ Or, If you want to check coverage:
86
+
87
+ ```bash
88
+ COVERAGE=on rake spec
89
+ ```
90
+
91
+ Issues
92
+ ------
93
+
94
+ Please use GitHub's [issue tracker](http://github.com/totalcareauto/unidata/issues).
95
+
96
+ Authors
97
+ -------
98
+
99
+ [Jeremy Israelsen](http://github.com/jisraelsen)
data/lib/unidata.rb ADDED
@@ -0,0 +1,33 @@
1
+ require 'udjrb'
2
+ require 'time'
3
+ require 'date'
4
+ require 'bigdecimal'
5
+ require 'unidata/extensions'
6
+ require 'unidata/connection'
7
+ require 'unidata/field'
8
+ require 'unidata/model'
9
+ require "unidata/version"
10
+
11
+ module Unidata
12
+ class << self
13
+ attr_reader :connection
14
+
15
+ def prepare_connection(config={})
16
+ @connection = Connection.new(config[:user], config[:password], config[:host], config[:data_dir])
17
+ end
18
+
19
+ def open_connection
20
+ begin
21
+ @connection.open
22
+ yield if block_given?
23
+ ensure
24
+ close_connection if block_given?
25
+ end
26
+ end
27
+
28
+ def close_connection
29
+ @connection.close
30
+ end
31
+ end
32
+ end
33
+
@@ -0,0 +1,111 @@
1
+ module Unidata
2
+ class Connection
3
+ attr_reader :user, :password, :host, :data_dir
4
+
5
+ def initialize(user, password, host, data_dir)
6
+ @user = user
7
+ @password = password
8
+ @host = host
9
+ @data_dir = data_dir
10
+ end
11
+
12
+ def open?
13
+ !@session.nil? && @session.is_active
14
+ end
15
+
16
+ def open
17
+ @session = UDJrb::Session.new user, password, host, data_dir
18
+ end
19
+
20
+ def close
21
+ @session.disconnect if @session
22
+ @session = nil
23
+ end
24
+
25
+ def exists?(filename, record_id)
26
+ exists = false
27
+
28
+ open_file(filename) do |file|
29
+ begin
30
+ file.read_field(record_id, 0)
31
+ exists = true
32
+ rescue Java::AsjavaUniobjects::UniFileException
33
+ end
34
+ end
35
+
36
+ exists
37
+ end
38
+
39
+ def read(filename, record_id)
40
+ record = nil
41
+
42
+ open_file(filename) do |file|
43
+ begin
44
+ record = Java::AsjavaUniclientlibs::UniDynArray.new(file.read(record_id))
45
+ rescue Java::AsjavaUniobjects::UniFileException
46
+ end
47
+ end
48
+
49
+ record
50
+ end
51
+
52
+ def read_field(filename, record_id, field)
53
+ value = nil
54
+
55
+ open_file(filename) do |file|
56
+ begin
57
+ value = file.read_field(record_id, field).to_s
58
+ rescue Java::AsjavaUniobjects::UniFileException
59
+ end
60
+ end
61
+
62
+ value
63
+ end
64
+
65
+ def write(filename, record_id, record)
66
+ record = record.to_unidata unless record.kind_of?(Java::AsjavaUniclientlibs::UniDynArray)
67
+
68
+ open_file(filename) do |file|
69
+ file.write(record_id, record)
70
+ end
71
+ end
72
+
73
+ def write_field(filename, record_id, value, field)
74
+ open_file(filename) do |file|
75
+ file.write_field(record_id, value, field)
76
+ end
77
+ end
78
+
79
+ def with_record_lock(filename, record_id, lock_flag=1)
80
+ open_file(filename) do |file|
81
+ retry_count = 0
82
+ begin
83
+ file.lock_record(record_id, lock_flag)
84
+ yield
85
+ rescue Java::AsjavaUniobjects::UniFileException
86
+ # try to obtain a record lock at most 3 times, then give up
87
+ if retry_count < 2
88
+ sleep 5
89
+
90
+ retry_count += 1
91
+ retry
92
+ else
93
+ raise
94
+ end
95
+ ensure
96
+ file.unlock_record(record_id)
97
+ end
98
+ end
99
+ end
100
+
101
+ private
102
+ def open_file(filename)
103
+ begin
104
+ file = @session.open filename
105
+ yield file
106
+ ensure
107
+ file.close
108
+ end
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,6 @@
1
+ require 'unidata/extensions/big_decimal'
2
+ require 'unidata/extensions/date'
3
+ require 'unidata/extensions/float'
4
+ require 'unidata/extensions/integer'
5
+ require 'unidata/extensions/string'
6
+ require 'unidata/extensions/time'
@@ -0,0 +1,17 @@
1
+ module Unidata
2
+ module Extensions
3
+ module BigDecimal
4
+ def to_unidata(value)
5
+ (value * 100).to_i
6
+ end
7
+
8
+ def from_unidata(value)
9
+ ::BigDecimal.new(value.to_s) / 100
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ class BigDecimal
16
+ extend Unidata::Extensions::BigDecimal
17
+ end
@@ -0,0 +1,19 @@
1
+ module Unidata
2
+ module Extensions
3
+ module Date
4
+ PICK_EPOCH = ::Date.parse('1968-01-01')
5
+
6
+ def to_unidata(value)
7
+ (value - PICK_EPOCH).to_i
8
+ end
9
+
10
+ def from_unidata(value)
11
+ PICK_EPOCH + value.to_i
12
+ end
13
+ end
14
+ end
15
+ end
16
+
17
+ class Date
18
+ extend Unidata::Extensions::Date
19
+ end
@@ -0,0 +1,17 @@
1
+ module Unidata
2
+ module Extensions
3
+ module Float
4
+ def to_unidata(value)
5
+ ::BigDecimal.to_unidata(value)
6
+ end
7
+
8
+ def from_unidata(value)
9
+ ::BigDecimal.from_unidata(value).to_f
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ class Float
16
+ extend Unidata::Extensions::Float
17
+ end
@@ -0,0 +1,17 @@
1
+ module Unidata
2
+ module Extensions
3
+ module Integer
4
+ def to_unidata(value)
5
+ value
6
+ end
7
+
8
+ def from_unidata(value)
9
+ value.to_i
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ class Integer
16
+ extend Unidata::Extensions::Integer
17
+ end
@@ -0,0 +1,17 @@
1
+ module Unidata
2
+ module Extensions
3
+ module String
4
+ def to_unidata(value)
5
+ value.upcase
6
+ end
7
+
8
+ def from_unidata(value)
9
+ value
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ class String
16
+ extend Unidata::Extensions::String
17
+ end
@@ -0,0 +1,17 @@
1
+ module Unidata
2
+ module Extensions
3
+ module Time
4
+ def to_unidata(value)
5
+ ::Date.to_unidata(value.to_date)
6
+ end
7
+
8
+ def from_unidata(value)
9
+ ::Date.from_unidata(value).to_time
10
+ end
11
+ end
12
+ end
13
+ end
14
+
15
+ class Time
16
+ extend Unidata::Extensions::Time
17
+ end
@@ -0,0 +1,19 @@
1
+ module Unidata
2
+ class Field
3
+ attr_reader :index, :name, :type, :formatter
4
+
5
+ def initialize(index, name, type=String)
6
+ @index = [*index]
7
+ @name = name
8
+ @type = type
9
+ end
10
+
11
+ def to_unidata(value)
12
+ type.to_unidata(value)
13
+ end
14
+
15
+ def from_unidata(value)
16
+ type.from_unidata(value)
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,106 @@
1
+ module Unidata
2
+ class Model
3
+ class << self
4
+ attr_accessor :filename
5
+
6
+ def connection
7
+ Unidata.connection
8
+ end
9
+
10
+ def fields
11
+ unless @fields
12
+ @fields = {}
13
+ field(0, :id)
14
+ end
15
+
16
+ @fields
17
+ end
18
+
19
+ def field?(name)
20
+ fields.keys.include?(name.to_sym)
21
+ end
22
+
23
+ def field(index, name, type=String)
24
+ fields[name.to_sym] = Field.new(index, name, type)
25
+ define_attribute_accessor(name)
26
+ end
27
+
28
+ def to_unidata(instance)
29
+ record = Java::AsjavaUniclientlibs::UniDynArray.new
30
+
31
+ instance.attributes.each do |key, value|
32
+ next if key == :id
33
+
34
+ field = fields[key]
35
+ record.replace *field.index, field.to_unidata(value)
36
+ end
37
+
38
+ record
39
+ end
40
+
41
+ def from_unidata(record)
42
+ instance = new
43
+
44
+ fields.each do |key, field|
45
+ next if key == :id
46
+
47
+ instance.send(
48
+ "#{key}=",
49
+ field.from_unidata(record.extract(*field.index).to_s)
50
+ )
51
+ end
52
+
53
+ instance
54
+ end
55
+
56
+ def exists?(id)
57
+ connection.exists?(filename, id)
58
+ end
59
+
60
+ def find(id)
61
+ record = connection.read(filename, id)
62
+
63
+ instance = from_unidata(record)
64
+ instance.id = id
65
+ instance
66
+ end
67
+
68
+ private
69
+ def define_attribute_accessor(attribute_name)
70
+ class_eval <<-end_eval
71
+ def #{attribute_name}
72
+ read_attribute(:#{attribute_name})
73
+ end
74
+
75
+ def #{attribute_name}=(value)
76
+ write_attribute(:#{attribute_name}, value)
77
+ end
78
+ end_eval
79
+ end
80
+ end
81
+
82
+ attr_reader :attributes
83
+
84
+ def initialize(attributes={})
85
+ @attributes = {}
86
+ attributes.each do |key,value|
87
+ next unless self.class.field?(key.to_sym)
88
+ @attributes[key.to_sym] = value
89
+ end
90
+ end
91
+
92
+ def save
93
+ record = self.class.to_unidata(self)
94
+ self.class.connection.write(self.class.filename, id, record)
95
+ end
96
+
97
+ private
98
+ def read_attribute(attribute_name)
99
+ @attributes[attribute_name.to_sym]
100
+ end
101
+
102
+ def write_attribute(attribute_name, value)
103
+ @attributes[attribute_name.to_sym] = value
104
+ end
105
+ end
106
+ end
@@ -0,0 +1,3 @@
1
+ module Unidata
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,25 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter '/spec/'
5
+ end
6
+ end
7
+
8
+ require 'rspec'
9
+ require 'unidata'
10
+
11
+ def package_local_constructor klass,*values
12
+ constructors = klass.java_class.declared_constructors
13
+ constructors.each do |c|
14
+ c.accessible = true
15
+ begin
16
+ return c.new_instance(*values).to_java
17
+ rescue TypeError
18
+ false
19
+ end
20
+ end
21
+ raise TypeError,"found no matching constructor for " + klass.to_s + "(" + value.class + ")"
22
+ end
23
+
24
+ RSpec.configure do |config|
25
+ end
@@ -0,0 +1,237 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unidata::Connection do
4
+ let(:connection) { Unidata::Connection.new('test', 'secret', 'localhost', 'tmp') }
5
+
6
+ describe '#initialize' do
7
+ it 'captures and assigns arguments' do
8
+ connection.user.should == 'test'
9
+ connection.password.should == 'secret'
10
+ connection.host.should == 'localhost'
11
+ connection.data_dir.should == 'tmp'
12
+ end
13
+ end
14
+
15
+ describe '#open?' do
16
+ context 'with existing active session' do
17
+ it 'returns true' do
18
+ UDJrb::Session.stub(:new).and_return(double('UDJrb::Session', :is_active => true))
19
+ connection.open
20
+ connection.open?.should == true
21
+ end
22
+ end
23
+
24
+ context 'with existing inactive session' do
25
+ it 'returns false' do
26
+ UDJrb::Session.stub(:new).and_return(double('UDJrb::Session', :is_active => false))
27
+ connection.open
28
+ connection.open?.should == false
29
+ end
30
+ end
31
+
32
+ context 'without existing session' do
33
+ it 'returns false' do
34
+ connection.open?.should == false
35
+ end
36
+ end
37
+ end
38
+
39
+ describe '#open' do
40
+ it 'creates a new session with config params' do
41
+ UDJrb::Session.should_receive(:new).with(connection.user, connection.password, connection.host, connection.data_dir)
42
+ connection.open
43
+ end
44
+ end
45
+
46
+ describe '#close' do
47
+ it 'disconnects the session' do
48
+ session = double('UDJrb::Session', :disconnect => nil)
49
+ UDJrb::Session.stub(:new).and_return(session)
50
+ connection.open
51
+
52
+ session.should_receive(:disconnect)
53
+ connection.close
54
+ end
55
+ end
56
+
57
+ describe '#exists?' do
58
+ before(:each) do
59
+ @file = double('UniFile', :close => nil, :read_field => nil)
60
+ @session = double('UDJrb::Session', :open => @file)
61
+
62
+ UDJrb::Session.stub(:new).and_return(@session)
63
+ connection.open
64
+ end
65
+
66
+ it 'opens file with filename' do
67
+ @session.should_receive(:open).with('TEST')
68
+ connection.exists?('TEST', 123)
69
+ end
70
+
71
+ it 'reads record_id field from file' do
72
+ @file.should_receive(:read_field).with(123, 0)
73
+ connection.exists?('TEST', 123)
74
+ end
75
+
76
+ it 'closes file' do
77
+ @file.should_receive(:close)
78
+ connection.exists?('TEST', 123)
79
+ end
80
+
81
+ context 'when file has given record_id' do
82
+ it 'returns true' do
83
+ @file.stub(:read_field).and_return('123')
84
+ connection.exists?('TEST', 123).should == true
85
+ end
86
+ end
87
+
88
+ context 'when file has no given record_id' do
89
+ it 'returns false' do
90
+ uni_file_exception = package_local_constructor Java::AsjavaUniobjects::UniFileException
91
+
92
+ @file.stub(:read_field).and_raise(uni_file_exception)
93
+ connection.exists?('TEST', 123).should == false
94
+ end
95
+ end
96
+ end
97
+
98
+ describe '#read' do
99
+ before(:each) do
100
+ @file = double('UniFile', :close => nil, :read => nil)
101
+ @session = double('UDJrb::Session', :open => @file)
102
+
103
+ UDJrb::Session.stub(:new).and_return(@session)
104
+ connection.open
105
+ end
106
+
107
+ it 'opens file in session' do
108
+ @session.should_receive(:open).with('TEST')
109
+ connection.read('TEST', 123)
110
+ end
111
+
112
+ it 'reads record from file' do
113
+ @file.should_receive(:read).with(123)
114
+ connection.read('TEST', 123)
115
+ end
116
+
117
+ it 'closes file' do
118
+ @file.should_receive(:close)
119
+ connection.read('TEST', 123)
120
+ end
121
+
122
+ context 'when record exists' do
123
+ it 'returns record as a Java::AsjavaUniclientlibs::UniDynArray' do
124
+ @file.stub(:read).and_return('')
125
+ connection.read('TEST', 123).should be_kind_of(Java::AsjavaUniclientlibs::UniDynArray)
126
+ end
127
+ end
128
+
129
+ context 'when record does not exist' do
130
+ it 'returns nil' do
131
+ uni_file_exception = package_local_constructor Java::AsjavaUniobjects::UniFileException
132
+
133
+ @file.stub(:read).and_raise(uni_file_exception)
134
+ connection.read('TEST', 123).should be_nil
135
+ end
136
+ end
137
+ end
138
+
139
+ describe '#read_field' do
140
+ before(:each) do
141
+ @file = double('UniFile', :close => nil, :read_field => nil)
142
+ @session = double('UDJrb::Session', :open => @file)
143
+
144
+ UDJrb::Session.stub(:new).and_return(@session)
145
+ connection.open
146
+ end
147
+
148
+ it 'opens file with filename' do
149
+ @session.should_receive(:open).with('TEST')
150
+ connection.read_field('TEST', 123, 5)
151
+ end
152
+
153
+ it 'reads field from file' do
154
+ @file.should_receive(:read_field).with(123, 5)
155
+ connection.read_field('TEST', 123, 5)
156
+ end
157
+
158
+ it 'closes file' do
159
+ @file.should_receive(:close)
160
+ connection.read_field('TEST', 123, 5)
161
+ end
162
+
163
+ context 'when field exists' do
164
+ it 'returns value as a String' do
165
+ @file.stub(:read_field).and_return(43245)
166
+ connection.read_field('TEST', 123, 5).should == '43245'
167
+ end
168
+ end
169
+
170
+ context 'when field does not exist' do
171
+ it 'returns nil' do
172
+ uni_file_exception = package_local_constructor Java::AsjavaUniobjects::UniFileException
173
+
174
+ @file.stub(:read_field).and_raise(uni_file_exception)
175
+ connection.read_field('TEST', 123, 5).should be_nil
176
+ end
177
+ end
178
+ end
179
+
180
+ describe '#write' do
181
+ before(:each) do
182
+ @file = double('UniFile', :close => nil, :write => nil)
183
+ @session = double('UDJrb::Session', :open => @file)
184
+ @record = Java::AsjavaUniclientlibs::UniDynArray.new
185
+
186
+ UDJrb::Session.stub(:new).and_return(@session)
187
+ connection.open
188
+ end
189
+
190
+ it 'opens file in session' do
191
+ @session.should_receive(:open).with('TEST')
192
+ connection.write('TEST', 123, @record)
193
+ end
194
+
195
+ it 'calls to_unidata on record if record not a Java::AsjavaUniclientlibs::UniDynArray' do
196
+ record = double('Record')
197
+ record.should_receive(:to_unidata).and_return(Java::AsjavaUniclientlibs::UniDynArray.new)
198
+
199
+ connection.write('TEST', 123, record)
200
+ end
201
+
202
+ it 'writes record to file' do
203
+ @file.should_receive(:write).with(123, @record)
204
+ connection.write('TEST', 123, @record)
205
+ end
206
+
207
+ it 'closes file' do
208
+ @file.should_receive(:close)
209
+ connection.write('TEST', 123, @record)
210
+ end
211
+ end
212
+
213
+ describe '#write_field' do
214
+ before(:each) do
215
+ @file = double('UniFile', :close => nil, :write_field => nil)
216
+ @session = double('UDJrb::Session', :open => @file)
217
+
218
+ UDJrb::Session.stub(:new).and_return(@session)
219
+ connection.open
220
+ end
221
+
222
+ it 'opens file with filename' do
223
+ @session.should_receive(:open).with('TEST')
224
+ connection.write_field('TEST', 123, 'value', 5)
225
+ end
226
+
227
+ it 'writes field to file' do
228
+ @file.should_receive(:write_field).with(123, 'value', 5)
229
+ connection.write_field('TEST', 123, 'value', 5)
230
+ end
231
+
232
+ it 'closes file' do
233
+ @file.should_receive(:close)
234
+ connection.write_field('TEST', 123, 'value', 5)
235
+ end
236
+ end
237
+ end
@@ -0,0 +1,113 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unidata::Field do
4
+ subject { Unidata::Field }
5
+
6
+ describe '#initialize' do
7
+ it 'captures and assigns arguments' do
8
+ field = subject.new(1, :date, Date)
9
+ field.index.should == [1]
10
+ field.name.should == :date
11
+ field.type.should == Date
12
+ end
13
+
14
+ it 'accepts multivalued indexes' do
15
+ field = subject.new([1,2], :name)
16
+ field.index.should == [1,2]
17
+ end
18
+
19
+ it 'defaults type to String' do
20
+ field = subject.new(2, :name)
21
+ field.type.should == String
22
+ end
23
+ end
24
+
25
+ describe '#to_unidata' do
26
+ context 'when type is Time' do
27
+ it 'converts value to pick time' do
28
+ field = subject.new(1, :created_at, Time)
29
+ field.to_unidata(Time.parse('2012-04-02 12:34:00')).should == 16163
30
+ end
31
+ end
32
+
33
+ context 'when type is Date' do
34
+ it 'converts value to pick time' do
35
+ field = subject.new(1, :created_on, Date)
36
+ field.to_unidata(Date.parse('2012-04-03')).should == 16164
37
+ end
38
+ end
39
+
40
+ context 'when type is String' do
41
+ it 'upcases value' do
42
+ field = subject.new(1, :name, String)
43
+ field.to_unidata('John Doe').should == 'JOHN DOE'
44
+ end
45
+ end
46
+
47
+ context 'when type is Float' do
48
+ it 'multiplies value by 100 and converts to an integer' do
49
+ field = subject.new(1, :price, Float)
50
+ field.to_unidata(123.32).should == 12332
51
+ end
52
+ end
53
+
54
+ context 'when type is BigDecimal' do
55
+ it 'multiplies value by 100 and converts to an integer' do
56
+ field = subject.new(1, :price, BigDecimal)
57
+ field.to_unidata(BigDecimal.new('123.32')).should == 12332
58
+ end
59
+ end
60
+
61
+ context 'when type is Integer' do
62
+ it 'does nothing' do
63
+ field = subject.new(1, :age, Integer)
64
+ field.to_unidata(45).should == 45
65
+ end
66
+ end
67
+ end
68
+
69
+ describe '#from_unidata' do
70
+ context 'when type is Time' do
71
+ it 'converts value from pick time' do
72
+ field = subject.new(1, :created_at, Time)
73
+ field.from_unidata(16163).should == Time.parse('2012-04-02 00:00:00')
74
+ end
75
+ end
76
+
77
+ context 'when type is Date' do
78
+ it 'converts value from pick time' do
79
+ field = subject.new(1, :created_on, Date)
80
+ field.from_unidata(16164).should == Date.parse('2012-04-03')
81
+ end
82
+ end
83
+
84
+ context 'when type is String' do
85
+ it 'does nothing' do
86
+ field = subject.new(1, :name, String)
87
+ field.from_unidata('JOHN DOE').should == 'JOHN DOE'
88
+ end
89
+ end
90
+
91
+ context 'when type is Float' do
92
+ it 'converts value to Float and divides by 100' do
93
+ field = subject.new(1, :price, Float)
94
+ field.from_unidata(12332).should == 123.32
95
+ end
96
+ end
97
+
98
+ context 'when type is BigDecimal' do
99
+ it 'converts value to BigDecimal and divides by 100' do
100
+ field = subject.new(1, :price, BigDecimal)
101
+ field.from_unidata(12332).should == BigDecimal.new('123.32')
102
+ end
103
+ end
104
+
105
+ context 'when type is Integer' do
106
+ it 'converts to an Integer' do
107
+ field = subject.new(1, :age, Integer)
108
+ field.from_unidata('45').should == 45
109
+ end
110
+ end
111
+ end
112
+ end
113
+
@@ -0,0 +1,185 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unidata::Model do
4
+ subject { Unidata::Model }
5
+
6
+ class Record < Unidata::Model
7
+ self.filename = 'TEST'
8
+
9
+ field 1, :name
10
+ field 2, :age, Integer
11
+ field 3, :birth_date, Date
12
+ field [4,1], :employer
13
+ field [4,2], :job_title
14
+ field [4,3], :salary, BigDecimal
15
+ end
16
+
17
+ describe '.connection' do
18
+ it 'returns the Unidata connection' do
19
+ Unidata.stub('connection').and_return(double('connection'))
20
+ subject.connection.should == Unidata.connection
21
+ end
22
+ end
23
+
24
+ describe '.field' do
25
+ it 'adds Field with given index, name, and type to fields hash' do
26
+ field = Record.fields[:age]
27
+ field.index.should == [2]
28
+ field.name.should == :age
29
+ field.type.should == Integer
30
+ end
31
+
32
+ it 'defines attribute reader/writer for field' do
33
+ obj = Record.new
34
+ obj.age = 25
35
+ obj.age.should == 25
36
+ end
37
+ end
38
+
39
+ describe '.to_unidata' do
40
+ before(:each) do
41
+ @obj = Record.new(
42
+ :id => 1234,
43
+ :name => 'John Doe',
44
+ :age => 25,
45
+ :birth_date => Date.today,
46
+ :employer => 'Awesome Company',
47
+ :job_title => 'Manager',
48
+ :salary => BigDecimal.new('60_000.00')
49
+ )
50
+ end
51
+
52
+ it 'converts model to UniDynArray' do
53
+ record = Record.to_unidata(@obj)
54
+ record.extract(1).to_s.should == 'JOHN DOE'
55
+ record.extract(2).to_s.should == '25'
56
+ record.extract(3).to_s.should == Date.to_unidata(Date.today).to_s
57
+ record.extract(4, 1).to_s.should == 'AWESOME COMPANY'
58
+ record.extract(4, 2).to_s.should == 'MANAGER'
59
+ record.extract(4, 3).to_s.should == '6000000'
60
+ end
61
+
62
+ it 'skips id field' do
63
+ record = Record.to_unidata(@obj)
64
+ record.extract(0).to_s.should == ''
65
+ end
66
+ end
67
+
68
+ describe '.from_unidata' do
69
+ before(:each) do
70
+ @record = Java::AsjavaUniclientlibs::UniDynArray.new
71
+ @record.replace 0, 123
72
+ @record.replace 1, 'JOHN DOE'
73
+ @record.replace 2, 25
74
+ @record.replace 3, Date.to_unidata(Date.today)
75
+ @record.replace 4, 1, 'AWESOME COMPANY'
76
+ @record.replace 4, 2, 'MANAGER'
77
+ @record.replace 4, 3, 6_000_000
78
+ end
79
+
80
+ it 'converts UniDynArray to model' do
81
+ obj = Record.from_unidata(@record)
82
+ obj.name.should == 'JOHN DOE'
83
+ obj.age.should == 25
84
+ obj.birth_date.should == Date.today
85
+ obj.employer.should == 'AWESOME COMPANY'
86
+ obj.job_title.should == 'MANAGER'
87
+ obj.salary.should == BigDecimal.new('60_000.00')
88
+ end
89
+
90
+ it 'skips id field' do
91
+ obj = Record.from_unidata(@record)
92
+ obj.id.should be_nil
93
+ end
94
+ end
95
+
96
+ describe '.exists?' do
97
+ before(:each) do
98
+ @connection = double('connection')
99
+ @connection.stub(:exists?).with('TEST', 123).and_return(true)
100
+ @connection.stub(:exists?).with('TEST', 234).and_return(false)
101
+
102
+ Unidata.stub(:connection).and_return(@connection)
103
+ end
104
+
105
+ it 'returns true if record with id exists in file' do
106
+ Record.exists?(123).should == true
107
+ end
108
+
109
+ it 'returns false if record with id does not exist in file' do
110
+ Record.exists?(234).should == false
111
+ end
112
+ end
113
+
114
+ describe '.find' do
115
+ before(:each) do
116
+ @record = Java::AsjavaUniclientlibs::UniDynArray.new
117
+ @record.replace 1, 'JOHN DOE'
118
+ @record.replace 2, 25
119
+ @record.replace 3, Date.to_unidata(Date.today)
120
+ @record.replace 4, 1, 'AWESOME COMPANY'
121
+ @record.replace 4, 2, 'MANAGER'
122
+ @record.replace 4, 3, 6_000_000
123
+
124
+ @connection = double('connection', :read => @record)
125
+ Unidata.stub(:connection).and_return(@connection)
126
+ end
127
+
128
+ it 'reads record from file' do
129
+ @connection.should_receive(:read).with('TEST', 123).and_return(@record)
130
+ Record.find(123)
131
+ end
132
+
133
+ it 'returns model' do
134
+ obj = Record.find(123)
135
+ obj.id.should == 123
136
+ obj.name.should == 'JOHN DOE'
137
+ obj.age.should == 25
138
+ obj.birth_date.should == Date.today
139
+ obj.employer.should == 'AWESOME COMPANY'
140
+ obj.job_title.should == 'MANAGER'
141
+ obj.salary.should == BigDecimal.new('60_000.00')
142
+ end
143
+ end
144
+
145
+ describe '#initialize' do
146
+ it 'captures provied attributes' do
147
+ instance = Record.new(:id => 123, :name => 'John Doe')
148
+ instance.attributes.should == { :id => 123, :name => 'John Doe' }
149
+ end
150
+
151
+ it 'ignores attributes that are not defined in fields' do
152
+ instance = Record.new(:id => 123, :name => 'John Doe', :nickname => 'J-Dog')
153
+ instance.attributes.should == { :id => 123, :name => 'John Doe' }
154
+ end
155
+ end
156
+
157
+ describe '#save' do
158
+ it 'writes record to file' do
159
+ connection = double('connection', :write => nil)
160
+ Unidata.stub(:connection).and_return(connection)
161
+
162
+ obj = Record.new(
163
+ :id => 1234,
164
+ :name => 'John Doe',
165
+ :age => 25,
166
+ :birth_date => Date.today,
167
+ :employer => 'Awesome Company',
168
+ :job_title => 'Manager',
169
+ :salary => BigDecimal.new('60_000.00')
170
+ )
171
+
172
+ record = Java::AsjavaUniclientlibs::UniDynArray.new
173
+ record.replace 1, 'JOHN DOE'
174
+ record.replace 2, 25
175
+ record.replace 3, Date.to_unidata(Date.today)
176
+ record.replace 4, 1, 'AWESOME COMPANY'
177
+ record.replace 4, 2, 'MANAGER'
178
+ record.replace 4, 3, 6_000_000
179
+
180
+ connection.should_receive(:write).with('TEST', 1234, record)
181
+ obj.save
182
+ end
183
+ end
184
+ end
185
+
@@ -0,0 +1,24 @@
1
+ require 'spec_helper'
2
+
3
+ describe Unidata do
4
+ before(:each) do
5
+ @config = { :user => 'test', :password => 'secret', :host => 'localhost', :data_dir => 'testdir' }
6
+ end
7
+
8
+ describe '.prepare_connection' do
9
+ it 'prepares a unidata connection with config options' do
10
+ Unidata.prepare_connection @config
11
+
12
+ Unidata.connection.should be_kind_of(Unidata::Connection)
13
+ Unidata.connection.user.should == @config[:user]
14
+ Unidata.connection.password.should == @config[:password]
15
+ Unidata.connection.host.should == @config[:host]
16
+ Unidata.connection.data_dir.should == @config[:data_dir]
17
+ end
18
+
19
+ it 'should not open the connection' do
20
+ Unidata.prepare_connection @config
21
+ Unidata.connection.should_not be_open
22
+ end
23
+ end
24
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: unidata
3
+ version: !ruby/object:Gem::Version
4
+ prerelease:
5
+ version: 0.0.1
6
+ platform: ruby
7
+ authors:
8
+ - Jeremy Israelsen
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-06-25 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: udjrb
16
+ version_requirements: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 0.0.3
21
+ none: false
22
+ requirement: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: 0.0.3
27
+ none: false
28
+ prerelease: false
29
+ type: :runtime
30
+ - !ruby/object:Gem::Dependency
31
+ name: rake
32
+ version_requirements: !ruby/object:Gem::Requirement
33
+ requirements:
34
+ - - ! '>='
35
+ - !ruby/object:Gem::Version
36
+ version: '0'
37
+ none: false
38
+ requirement: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ! '>='
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ none: false
44
+ prerelease: false
45
+ type: :development
46
+ - !ruby/object:Gem::Dependency
47
+ name: rspec
48
+ version_requirements: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ~>
51
+ - !ruby/object:Gem::Version
52
+ version: '2.10'
53
+ none: false
54
+ requirement: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ~>
57
+ - !ruby/object:Gem::Version
58
+ version: '2.10'
59
+ none: false
60
+ prerelease: false
61
+ type: :development
62
+ - !ruby/object:Gem::Dependency
63
+ name: simplecov
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ~>
67
+ - !ruby/object:Gem::Version
68
+ version: '0.6'
69
+ none: false
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ~>
73
+ - !ruby/object:Gem::Version
74
+ version: '0.6'
75
+ none: false
76
+ prerelease: false
77
+ type: :development
78
+ description: A simple ORM for Rocket's UniData database
79
+ email:
80
+ - jisraelsen@gmail.com
81
+ executables: []
82
+ extensions: []
83
+ extra_rdoc_files: []
84
+ files:
85
+ - lib/unidata.rb
86
+ - lib/unidata/connection.rb
87
+ - lib/unidata/extensions.rb
88
+ - lib/unidata/extensions/big_decimal.rb
89
+ - lib/unidata/extensions/date.rb
90
+ - lib/unidata/extensions/float.rb
91
+ - lib/unidata/extensions/integer.rb
92
+ - lib/unidata/extensions/string.rb
93
+ - lib/unidata/extensions/time.rb
94
+ - lib/unidata/field.rb
95
+ - lib/unidata/model.rb
96
+ - lib/unidata/version.rb
97
+ - LICENSE
98
+ - README.md
99
+ - spec/spec_helper.rb
100
+ - spec/unidata/connection_spec.rb
101
+ - spec/unidata/field_spec.rb
102
+ - spec/unidata/model_spec.rb
103
+ - spec/unidata_spec.rb
104
+ homepage: http://github.com/totalcareauto/unidata
105
+ licenses: []
106
+ post_install_message:
107
+ rdoc_options: []
108
+ require_paths:
109
+ - lib
110
+ required_ruby_version: !ruby/object:Gem::Requirement
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ none: false
116
+ required_rubygems_version: !ruby/object:Gem::Requirement
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ none: false
122
+ requirements: []
123
+ rubyforge_project:
124
+ rubygems_version: 1.8.24
125
+ signing_key:
126
+ specification_version: 3
127
+ summary: A simple ORM for Rocket's UniData database
128
+ test_files:
129
+ - spec/spec_helper.rb
130
+ - spec/unidata/connection_spec.rb
131
+ - spec/unidata/field_spec.rb
132
+ - spec/unidata/model_spec.rb
133
+ - spec/unidata_spec.rb
134
+ ...