drive_time 0.0.3

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.
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ module DriveTime
4
+
5
+ describe JoinBuilder do
6
+
7
+ before(:each) do
8
+ @join_builder = JoinBuilder.new
9
+ end
10
+
11
+ it "should combine values into a single value" do
12
+ # All present
13
+ name_fields = ['Key1', 'Key2', 'Key3']
14
+ row_map = {'Key1' => 'Value1', 'Key2' => 'Value2', 'Key3' => 'Value3'}
15
+ @join_builder.build(name_fields, row_map).should == 'value1_value2_value3'
16
+
17
+ end
18
+
19
+ it "should ignore empty fields so long as they exist" do
20
+ name_fields = ['Key1', 'Key2', 'Key3']
21
+ row_map = {'Key1' => 'Value1', 'Key2' => '', 'Key3' => 'Value3'}
22
+ @join_builder.build(name_fields, row_map).should == 'value1_value3'
23
+ end
24
+
25
+ it "should not add anything to a single name" do
26
+ name_fields = ['Key3']
27
+ row_map = {'Key1' => 'Value1', 'Key2' => 'Value2', 'Key3' => 'Value3'}
28
+ @join_builder.build(name_fields, row_map).should == 'value3'
29
+ end
30
+
31
+ it "should raise a MissingFieldError if a field is missing" do
32
+
33
+ name_fields = ['Key1']
34
+ row_map = {}
35
+
36
+ expect { @join_builder.build(name_fields, row_map) }.to raise_error NameBuilder::MissingFieldError
37
+ end
38
+
39
+ it "should raise a NoFieldsError if all fields are missing" do
40
+
41
+ name_fields = ['Key1', 'Key2', 'Key3']
42
+ row_map = {'Key1' => '', 'Key2' => '', 'Key3' => ''}
43
+
44
+ expect { @join_builder.build(name_fields, row_map) }.to raise_error NameBuilder::NoFieldsError
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+
3
+ module DriveTime
4
+
5
+ describe NameBuilder do
6
+
7
+ before(:each) do
8
+ @name_builder = NameBuilder.new
9
+ end
10
+
11
+ it "should combine names into a single name, adding a '.' for a middle initial" do
12
+ # All present
13
+ name_fields = ['First Name', 'Middle Names', 'Last Name']
14
+ row_map = {'First Name' => 'George', 'Middle Names' => 'W', 'Last Name' => 'Bush'}
15
+ @name_builder.build(name_fields, row_map).should == 'george_w._bush'
16
+ end
17
+
18
+ it "should combine names into a single name, adding no '.' for any longer middle name" do
19
+ # All present
20
+ name_fields = ['First Name', 'Middle Names', 'Last Name']
21
+ row_map = {'First Name' => 'George', 'Middle Names' => 'Wo', 'Last Name' => 'Bush'}
22
+ @name_builder.build(name_fields, row_map).should == 'george_wo_bush'
23
+ end
24
+
25
+ end
26
+ end
@@ -0,0 +1,77 @@
1
+ require 'spec_helper'
2
+
3
+ module DriveTime
4
+
5
+ describe ClassNameMap do
6
+
7
+ before :each do
8
+ @class_name_map = ClassNameMap.new
9
+ @class_a = "ClassA"
10
+ @class_b = "ClassB"
11
+ @class_c = "ClassC"
12
+ @class_d = "ClassD"
13
+ @class_e = "ClassD"
14
+ @class_name_map.save_mapping(@class_c, @class_d)
15
+ end
16
+
17
+ describe "when saving class mapping" do
18
+
19
+ context "when no mapped class name is given" do
20
+ it "should return the classname" do
21
+ @class_name_map.save_mapping(@class_a).should == @class_a
22
+ end
23
+ end
24
+
25
+ context "when a mapped class name is given" do
26
+ it "should return the mapping" do
27
+ @class_name_map.save_mapping(@class_a, @class_b).should == @class_b
28
+ end
29
+ end
30
+
31
+ end
32
+
33
+ describe "when resolving the original from mapped" do
34
+
35
+ context "when a mapping exists" do
36
+
37
+ it "should return the mapping" do
38
+ @class_name_map.save_mapping(@class_a, @class_b)
39
+ @class_name_map.resolve_original_from_mapped(@class_b).should == @class_a
40
+ end
41
+
42
+ end
43
+
44
+ context "when no mapping exists" do
45
+
46
+ it "should return the class" do
47
+ @class_name_map.save_mapping(@class_a)
48
+ @class_name_map.resolve_original_from_mapped(@class_a).should == @class_a
49
+ end
50
+
51
+ end
52
+
53
+ end
54
+
55
+ describe "when resolving the mapped from original" do
56
+
57
+ context "when a mapping exists" do
58
+
59
+ it "should return the original" do
60
+ @class_name_map.save_mapping(@class_a, @class_b)
61
+ @class_name_map.resolve_mapped_from_original(@class_a).should == @class_b
62
+ end
63
+
64
+ end
65
+
66
+ context "when no mapping exists" do
67
+
68
+ it "should return the class" do
69
+ @class_name_map.resolve_mapped_from_original(@class_e).should == @class_e
70
+ end
71
+
72
+ end
73
+
74
+ end
75
+
76
+ end
77
+ end
@@ -0,0 +1,64 @@
1
+ require 'spec_helper'
2
+
3
+ module DriveTime
4
+
5
+ describe WorksheetConverter do
6
+
7
+ before(:each) do
8
+ @worksheet_converter = WorksheetConverter.new(nil, nil, nil, nil)
9
+ end
10
+
11
+ context 'build_id_for_model' do
12
+
13
+ it 'should build correct id for model using basic key' do
14
+
15
+ class WorksheetConverter
16
+ public :build_id_for_model
17
+ end
18
+
19
+ mapping = {:key => 'name'}
20
+ @worksheet_converter.row_map = {'name' => 'John'}
21
+
22
+ @worksheet_converter.build_id_for_model(mapping).should == 'john'
23
+ end
24
+
25
+ it 'should build correct id for model using join builder' do
26
+
27
+ class WorksheetConverter
28
+ public :build_id_for_model
29
+ end
30
+
31
+ mapping = {:key => {:builder => 'join', :from_fields => ['one', 'two', 'three'] } }
32
+ @worksheet_converter.row_map = {'one' => 'Apple', 'two' => 'Orange', 'three' => 'Plum'}
33
+
34
+ @worksheet_converter.build_id_for_model(mapping).should == 'apple_orange_plum'
35
+ end
36
+
37
+ it 'should build correct id for model using name builder' do
38
+
39
+ class WorksheetConverter
40
+ public :build_id_for_model
41
+ end
42
+
43
+ mapping = {:key => {:builder => 'name', :from_fields => ['forename', 'middle_name', 'surname'] } }
44
+ @worksheet_converter.row_map = {'forename' => 'George', 'middle_name' => 'W', 'surname' => 'Bush'}
45
+
46
+ @worksheet_converter.build_id_for_model(mapping).should == 'george_w._bush'
47
+ end
48
+
49
+ it 'should raise a NoFieldNameError if no field exists with key name' do
50
+
51
+ class WorksheetConverter
52
+ public :build_id_for_model
53
+ end
54
+
55
+ mapping = {:key => 'nonsense'}
56
+ @worksheet_converter.row_map = {'name' => 'John'}
57
+
58
+ expect { @worksheet_converter.build_id_for_model(mapping) }.to raise_error WorksheetConverter::NoFieldNameError
59
+ end
60
+
61
+ end
62
+
63
+ end
64
+ end
@@ -0,0 +1,130 @@
1
+ require "spec_helper"
2
+ require "google_drive"
3
+
4
+ module DriveTime
5
+
6
+ describe FieldExpander do
7
+
8
+ before :each do
9
+ @loader = Loader.new
10
+ @loader.stub :begin_session
11
+ @field_expander = FieldExpander.new(@loader)
12
+ @valid_file_path = "valid_file_path"
13
+
14
+ @invalid_token = "invalid_token"
15
+ @valid_expand_file_token = "expand_file"
16
+ @valid_expand_file_token_with_filename = "expand_file[#{@valid_file_path}]"
17
+ @valid_expand_spreadsheet_token = "expand_spreadsheet"
18
+ @valid_expand_spreadsheet_token_with_filename = "expand_spreadsheet[#{@valid_file_path}]"
19
+ @file = {name: 'file'} # need something in the object or Ruby treats it as blank
20
+ @file.stub :initialize
21
+ @file_contents = "12345"
22
+ @model_key = "model_key"
23
+ @worksheet = {name: 'worksheet'}
24
+ @spreadsheet = {name: 'spreadsheet'}
25
+ end
26
+
27
+ context "when supplied with a field containig an invalid token" do
28
+
29
+ it "should raise a TokenExpansionError" do
30
+ expect { @field_expander.expand(@invalid_token, @model_key) }.to raise_error TokenExpansionError
31
+ end
32
+
33
+ end
34
+
35
+ context "when supplied with a field containig an 'expand_file' token" do
36
+
37
+ context "when the file exists" do
38
+
39
+ it "should load the file" do
40
+ @loader.should_receive(:load_file_direct).with("#{@model_key}.txt").and_return(@file)
41
+ @file.should_receive(:download_to_string).and_return(@file_contents)
42
+ @field_expander.expand(@valid_expand_file_token, @model_key).should == @file_contents
43
+ end
44
+
45
+ end
46
+
47
+ context "when the file doesn't exist" do
48
+
49
+ it "should raise a TokenExpansionError" do
50
+ @loader.stub(:load_file_direct).and_return(nil)
51
+ expect { @field_expander.expand(@valid_expand_file_token, @model_key) }.to raise_error TokenExpansionError
52
+ end
53
+
54
+ end
55
+ end
56
+
57
+ context "when supplied with a field containig an 'expand_file' token and a filename" do
58
+
59
+ context "when the file exists" do
60
+
61
+ it "should load the file " do
62
+ @loader.should_receive(:load_file_direct).with("#{@valid_file_path}.txt").and_return(@file)
63
+ @file.should_receive(:download_to_string).and_return(@file_contents)
64
+ @field_expander.expand(@valid_expand_file_token_with_filename, @model_key).should == @file_contents
65
+ end
66
+
67
+ end
68
+
69
+ context "when the file doesn't exist" do
70
+
71
+ it "should raise a TokenExpansionError" do
72
+ @loader.stub(:load_file_direct).and_return(nil)
73
+ expect { @field_expander.expand(@valid_expand_file_token_with_filename, @model_key) }.to raise_error TokenExpansionError
74
+ end
75
+
76
+ end
77
+
78
+ end
79
+
80
+ context "when supplied with a field containig an 'expand_spreadsheet' token" do
81
+
82
+ context "when the spreadsheet exists" do
83
+
84
+ it "should load the spreadsheet" do
85
+ @file.stub(:worksheets).and_return([@worksheet])
86
+ @loader.should_receive(:load_spreadsheet_direct).with(@model_key).and_return(@file)
87
+ @field_expander.should_receive(:expand_worksheet).with(@worksheet)
88
+ @field_expander.expand(@valid_expand_spreadsheet_token, @model_key)
89
+ end
90
+
91
+ end
92
+
93
+ context "when the spreadsheet doesn't exist" do
94
+
95
+ it "should raise a TokenExpansionError" do
96
+ @loader.stub(:load_spreadsheet_direct).and_return(nil)
97
+ expect { @field_expander.expand(@valid_expand_spreadsheet_token, @model_key) }.to raise_error TokenExpansionError
98
+ end
99
+
100
+ end
101
+
102
+ end
103
+
104
+ context "when supplied with a field containig an 'expand_spreadsheet' token and a spreadsheet name" do
105
+
106
+ context "when the spreadsheet exists" do
107
+
108
+ it "should load the spreadsheet " do
109
+ @file.stub(:worksheets).and_return([@worksheet])
110
+ @loader.should_receive(:load_spreadsheet_direct).with(@valid_file_path).and_return(@file)
111
+ @field_expander.should_receive(:expand_worksheet).with(@worksheet).and_return(@file_contents)
112
+ @field_expander.expand(@valid_expand_spreadsheet_token_with_filename, @model_key)
113
+ end
114
+
115
+ end
116
+
117
+ context "when the spreadsheet doesn't exist" do
118
+
119
+ it "should raise a TokenExpansionError" do
120
+ @loader.stub(:load_spreadsheet_direct).and_return(nil)
121
+ expect { @field_expander.expand(@valid_expand_spreadsheet_token_with_filename, @model_key) }.to raise_error TokenExpansionError
122
+ end
123
+
124
+ end
125
+
126
+ end
127
+
128
+ end
129
+
130
+ end
@@ -0,0 +1,111 @@
1
+ require 'spec_helper'
2
+
3
+ module DriveTime
4
+
5
+ VALID_SPREADSHEET_1_TITLE = 'Fixture 1'
6
+ VALID_SPREADSHEET_2_TITLE = 'Fixture 2'
7
+ INVALID_SPREADSHEET_TITLE = 'Invalid Title xccdtyyehdyd56ejr6'
8
+
9
+ describe Loader do
10
+
11
+ def last_access_time_for_cached_file(title)
12
+ cached_directory = ENV['CACHED_DIR']
13
+ file_name = "#{title}.yml"
14
+ file_path = File.join(cached_directory, file_name)
15
+ File.atime(file_path).to_i
16
+ end
17
+
18
+ def clear_cache_dir
19
+ cached_directory = ENV['CACHED_DIR']
20
+ FileUtils.rm Dir.glob("#{cached_directory}/*")
21
+ end
22
+
23
+ def cached_file_exists(file_name)
24
+ cached_directory = ENV['CACHED_DIR']
25
+ file_name = "#{VALID_SPREADSHEET_1_TITLE}.yml"
26
+ file_path = File.join(cached_directory, file_name)
27
+ return File.exists? file_path
28
+ end
29
+
30
+ before(:each ) do
31
+ @loader = Loader.new
32
+ end
33
+
34
+ context 'When not using cache' do
35
+
36
+ context 'when accessing a spreadsheet' do
37
+
38
+ it "should raise a SpreadsheetNotFoundError if a spreadsheet doesn't exist" do
39
+ expect{ @loader.load_spreadsheet(INVALID_SPREADSHEET_TITLE, false) }.to raise_error(Loader::SpreadsheetNotFoundError)
40
+ end
41
+
42
+ it "should download a Spreadsheet sucessfully" do
43
+ @loader.load_spreadsheet(VALID_SPREADSHEET_1_TITLE, false).title.should == VALID_SPREADSHEET_1_TITLE
44
+ end
45
+
46
+ end
47
+
48
+ context 'when accessing a worksheet from with a loaded spreadsheet' do
49
+
50
+ before(:each) do
51
+ @spreadsheet = @loader.load_spreadsheet(VALID_SPREADSHEET_1_TITLE, false)
52
+ end
53
+
54
+ it "should raise a SpreadsheetNotFoundError if a worksheet doesn't exist" do
55
+ expect{ @loader.load_worksheet_from_spreadsheet(@spreadsheet, 'nmgsgscg', false) }.to raise_error(Loader::WorksheetNotFoundError)
56
+ end
57
+
58
+ it "should download a Worksheet sucessfully" do
59
+ @loader.load_worksheet_from_spreadsheet(@spreadsheet, 'Label', false).title.should == 'Label'
60
+ end
61
+
62
+ end
63
+ end
64
+
65
+ context 'When using cache' do
66
+
67
+ before(:each) do
68
+ @spreadsheet = @loader.load_spreadsheet(VALID_SPREADSHEET_1_TITLE, false)
69
+ # Save the time so we can check file access
70
+ @before = Time.now.to_i
71
+ end
72
+
73
+ context 'when accessing a spreadsheet' do
74
+ it "should pull a Spreadsheet from the cache if it exists" do
75
+ @loader.load_spreadsheet(VALID_SPREADSHEET_1_TITLE).title.should == VALID_SPREADSHEET_1_TITLE
76
+ last_access_time_for_cached_file(VALID_SPREADSHEET_1_TITLE).should <= @before
77
+ end
78
+
79
+ it "should download a Spreadsheet if it isn't in the cache" do
80
+ clear_cache_dir
81
+ @loader.load_spreadsheet(VALID_SPREADSHEET_1_TITLE, false).title.should == VALID_SPREADSHEET_1_TITLE
82
+ end
83
+
84
+ it "should save the spreadsheet to the cache" do
85
+ clear_cache_dir
86
+ @loader.load_spreadsheet(VALID_SPREADSHEET_1_TITLE)
87
+ cached_file_exists(VALID_SPREADSHEET_1_TITLE).should be_true
88
+ end
89
+
90
+ it "should save the spreadsheet's worksheets to the cache" do
91
+ clear_cache_dir
92
+ @loader.load_spreadsheet(VALID_SPREADSHEET_1_TITLE)
93
+ cached_file_exists('Label').should be_true
94
+ cached_file_exists('Act').should be_true
95
+ cached_file_exists('Album').should be_true
96
+ cached_file_exists('Group').should be_true
97
+ end
98
+
99
+ end
100
+
101
+ context 'when accessing a worksheet from with a loaded spreadsheet' do
102
+
103
+ it "should download a Spreadsheet sucessfully" do
104
+ @loader.load_worksheet_from_spreadsheet(@spreadsheet, 'Label').title.should == 'Label'
105
+ end
106
+
107
+ end
108
+
109
+ end
110
+ end
111
+ end
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+ require 'active_record'
3
+
4
+ module DriveTime
5
+
6
+ describe ModelStore do
7
+
8
+ class ModelA
9
+ end
10
+
11
+ class ModelB
12
+ end
13
+
14
+ before(:each) do
15
+ @model_store = ModelStore.new
16
+ @model_a = ModelA.new
17
+ @model_b = ModelB.new
18
+ end
19
+
20
+ describe 'when models are added' do
21
+
22
+ it 'should allow an added model to be retrieved' do
23
+ @model_store.add_model(@model_a, 'model_a', ModelA)
24
+ @model_store.get_model(ModelA, 'model_a').should == @model_a
25
+ end
26
+
27
+ describe 'when the same model is added twice' do
28
+
29
+ it 'should raise a ModelAddedTwiceError' do
30
+ @model_store.add_model(@model_a, 'model_a', ModelA)
31
+ expect { @model_store.add_model(@model_a, 'model_a', ModelA) }.to raise_error(ModelStore::ModelAddedTwiceError)
32
+ end
33
+
34
+ end
35
+ end
36
+
37
+ describe 'when models are retieved' do
38
+
39
+ it 'should raise a NoModelsOfClassInStoreError if no model is stored of the given type' do
40
+ @model_store.add_model(@model_a, 'model_a', ModelA)
41
+ expect { @model_store.get_model(ModelB, 'model_a') }.to raise_error(ModelStore::NoModelsOfClassInStoreError)
42
+ end
43
+
44
+ it 'should raise a NoModelOfClassWithKeyInStoreError if no model is stored of the given type with the given key' do
45
+ @model_store.add_model(@model_a, 'model_a', ModelA)
46
+ expect { @model_store.get_model(ModelA, 'model_b') }.to raise_error(ModelStore::NoModelOfClassWithKeyInStoreError)
47
+ end
48
+
49
+ end
50
+
51
+ end
52
+ end
@@ -0,0 +1,44 @@
1
+ require 'spec_helper'
2
+
3
+ # Mapped from Group
4
+
5
+ module DriveTime
6
+
7
+ describe DriveTime do
8
+
9
+ it 'should process string correctly' do
10
+
11
+ input_string = ' a Test STRING-with-spaces- AND hyphens '
12
+ # All lower case
13
+ # Underscores replace speces and hyphens
14
+ # Leading and trailing whitespace is removed
15
+ expected_string = 'a_test_string-with-spaces-_and_hyphens'
16
+ result_string = DriveTime.underscore_from_text input_string
17
+ result_string.should == expected_string
18
+ end
19
+
20
+ it 'should process a title to a class' do
21
+ input_string = "Nonsense Things"
22
+ expected_string = "NonsenseThing"
23
+ result_string = DriveTime.class_name_from_title input_string
24
+ result_string.should == expected_string
25
+ end
26
+
27
+ it 'should only treat yes and y (in any case) as affirmative' do
28
+ # Positive
29
+ DriveTime.is_affirmative?('yes').should be_true
30
+ DriveTime.is_affirmative?('YES').should be_true
31
+ DriveTime.is_affirmative?('Yes').should be_true
32
+ DriveTime.is_affirmative?('y').should be_true
33
+ DriveTime.is_affirmative?('Y').should be_true
34
+ DriveTime.is_affirmative?(' Yes ').should be_true
35
+ # Negative
36
+ DriveTime.is_affirmative?('No').should be_false
37
+ DriveTime.is_affirmative?('').should be_false
38
+ DriveTime.is_affirmative?('N').should be_false
39
+ DriveTime.is_affirmative?('Yeses').should be_false
40
+ DriveTime.is_affirmative?('Example').should be_false
41
+ end
42
+
43
+ end
44
+ end
@@ -0,0 +1,55 @@
1
+ namespace: DriveTime
2
+ spreadsheets:
3
+ - title: Fixture 1
4
+ worksheets:
5
+ - title: Group
6
+ map_to_class: Act
7
+ key: name
8
+ fields:
9
+ - name: name
10
+ - name: formed
11
+ associations:
12
+ - name: member
13
+ builder: multi
14
+
15
+ - title: Album
16
+ key: name
17
+ fields:
18
+ - name: year
19
+ associations:
20
+ - name: label
21
+ builder: use_fields
22
+ field_names: [label_1, label_2, label_3]
23
+ singular: true
24
+ - name: act
25
+ singular: true
26
+
27
+ - title: Label
28
+ key: name
29
+ fields:
30
+ - name: genre
31
+ - name: website
32
+
33
+ - title: Member
34
+ key: name
35
+ fields:
36
+ - name: name
37
+ - name: real_name
38
+ # from_fields: [forename, middle_names, surname]
39
+ - name: year_of_birth
40
+ - name: year_of_death
41
+
42
+ - title: Fixture 2
43
+ dependencies: [Fixture 1]
44
+ worksheets:
45
+ - title: Track
46
+ key:
47
+ builder: join
48
+ from_fields: [name, remix]
49
+ fields:
50
+ - name: name
51
+ - name: remix
52
+ - name: duration
53
+ associations:
54
+ - name: album
55
+ inverse: true
@@ -0,0 +1,48 @@
1
+ require 'spec_helper'
2
+
3
+ class ModelBase
4
+
5
+ def initialize(data, params)
6
+ end
7
+
8
+ def save!
9
+ end
10
+ end
11
+
12
+ module DriveTime
13
+
14
+ class Act < ModelBase
15
+ attr_accessor :members
16
+ def initialize(data, params)
17
+ self.members = Array.new
18
+ end
19
+ end
20
+
21
+ class Album < ModelBase
22
+ attr_accessor :label
23
+ attr_accessor :act
24
+ attr_accessor :tracks
25
+ def initialize(data, params)
26
+ self.tracks = Array.new
27
+ end
28
+ end
29
+
30
+ class Label < ModelBase; end
31
+
32
+ class Member < ModelBase; end
33
+
34
+ class Track < ModelBase; end
35
+
36
+ describe DriveTime do
37
+
38
+ context 'with full spreadsheet and mapping' do
39
+ it 'should load spreadsheet and map to models' do
40
+ mappings_path = File.join(File.dirname(__FILE__),'fixtures/mapping.yml')
41
+ converter = SpreadsheetsConverter.new
42
+ converter.load mappings_path
43
+ end
44
+
45
+ end
46
+
47
+ end
48
+ end
@@ -0,0 +1,6 @@
1
+ require 'dotenv'
2
+ require 'drive_time'
3
+ require "log4r"
4
+
5
+ Dotenv.load
6
+ DriveTime::log_level = Log4r::DEBUG