unidata 0.0.1

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