tinkit 0.0.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.
Files changed (51) hide show
  1. data/LICENSE +176 -0
  2. data/README +11 -0
  3. data/Rakefile +75 -0
  4. data/lib/glue_envs/couchrest/couchrest_attachment_handler.rb +260 -0
  5. data/lib/glue_envs/couchrest/couchrest_files_mgr.rb +198 -0
  6. data/lib/glue_envs/couchrest_glue_env.rb +536 -0
  7. data/lib/glue_envs/files_mgr_base.rb +51 -0
  8. data/lib/glue_envs/filesystem/filesystem_files_mgr.rb +187 -0
  9. data/lib/glue_envs/filesystem_glue_env.rb +395 -0
  10. data/lib/glue_envs/mysql/mysql_files_mgr.rb +175 -0
  11. data/lib/glue_envs/mysql_glue_env.rb +428 -0
  12. data/lib/glue_envs/sdb_s3/sdb_s3_files_mgr.rb +314 -0
  13. data/lib/glue_envs/sdb_s3_glue_env.rb +248 -0
  14. data/lib/helpers/camel.rb +21 -0
  15. data/lib/helpers/filesystem_helpers.rb +27 -0
  16. data/lib/helpers/hash_helpers.rb +74 -0
  17. data/lib/helpers/log_helper.rb +34 -0
  18. data/lib/helpers/mime_types_new.rb +126 -0
  19. data/lib/helpers/old_more_open_struct.rb +28 -0
  20. data/lib/helpers/require_helper.rb +45 -0
  21. data/lib/helpers/tk_escape.rb +17 -0
  22. data/lib/midas/bufs_data_structure.rb +84 -0
  23. data/lib/midas/node_element_operations.rb +264 -0
  24. data/lib/tinkit.rb +38 -0
  25. data/lib/tinkit_base_node.rb +733 -0
  26. data/lib/tinkit_node_factory.rb +47 -0
  27. data/spec/couchrest_files_mgr_spec.rb +551 -0
  28. data/spec/couchrest_glue_spec.rb +246 -0
  29. data/spec/filesystem_files_mgr_spec.rb +236 -0
  30. data/spec/filesystem_glue_spec.rb +243 -0
  31. data/spec/filesystem_helpers_spec.rb +42 -0
  32. data/spec/helpers/bufs_node_builder.rb +17 -0
  33. data/spec/helpers/bufs_sample_dataset.rb +160 -0
  34. data/spec/helpers/bufs_test_environments.rb +81 -0
  35. data/spec/helpers/tmp_view_cleaner.rb +15 -0
  36. data/spec/lib_helpers/tk_escape_spec.rb +45 -0
  37. data/spec/mysql_files_mgr_spec.rb +250 -0
  38. data/spec/mysql_glue_spec.rb +214 -0
  39. data/spec/node_element_operations_spec.rb +392 -0
  40. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec1.rb +82 -0
  41. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec2.rb +68 -0
  42. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec3.rb +80 -0
  43. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec4.rb +110 -0
  44. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec5.rb +84 -0
  45. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec6.rb +83 -0
  46. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec7.rb +101 -0
  47. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec8.rb +92 -0
  48. data/spec/sdb_s3_files_mgr_spec/sdb_s3_files_mgr_spec_all.rb +266 -0
  49. data/spec/sdb_s3_glue_spec.rb +230 -0
  50. data/spec/tinkit_node_factory_spec.rb +1108 -0
  51. metadata +114 -0
@@ -0,0 +1,81 @@
1
+ DirEnvHelpers = File.dirname(__FILE__)
2
+ DirBaseEnvHelpers = File.join(DirEnvHelpers, '../../')
3
+ DirFixEnvHelpers = File.join(DirBaseEnvHelpers, 'bufs_fixtures/bufs_fixtures')
4
+
5
+ #include fixtures
6
+ require DirFixEnvHelpers
7
+
8
+ require 'couchrest'
9
+ node_db_name = "http://bufs.younghawk.org:5984/bufs_test_spec/"
10
+ CouchDB = TinkitFixtures::CouchDB #CouchRest.database!(node_db_name)
11
+ CouchDB.compact!
12
+ CouchDB2 = TinkitFixtures::CouchDB2
13
+ CouchDB2.compact!
14
+ FileSystem1 = "/home/bufs/bufs/sandbox_for_specs/file_system_specs/group1"
15
+ FileSystem2 = "/home/bufs/bufs/sandbox_for_specs/file_system_specs/group2"
16
+
17
+ require File.join(DirBaseEnvHelpers, 'lib/tinkit_node_factory')
18
+
19
+ module UserNodeSpecHelpers
20
+ TinkitNodeLibs = [File.join(DirBaseEnvHelpers,'lib/glue_envs/bufs_couchrest_glue_env')]
21
+ TinkitNodeIncludes = [:CouchRestEnv]
22
+ TinkitFileLibs = [File.join(DirBaseEnvHelpers, 'lib/glue_envs/bufs_filesystem_glue_env')]
23
+ TinkitFileIncludes = [:FileSystemEnv]
24
+ end
25
+
26
+ #TODO: Combine this and the next module
27
+ module NodeHelper
28
+ def self.env_builder(model_name, node_class_id, user_id, path, host = nil)
29
+ #binding data (note this occurs in two different places in the env)
30
+
31
+ key_fields = {:required_keys => [:my_category],
32
+ :primary_key => :my_category }
33
+ #data model
34
+ field_op_set ={:my_category => :static_ops,
35
+ :description => :replace_ops,
36
+ :parent_categories => :list_ops,
37
+ :links => :key_list_ops }
38
+ #op_set_mod => <Using default definitions>
39
+
40
+ data_model = {:field_op_set => field_op_set, :key_fields => key_fields}
41
+
42
+ #persistence layer model
43
+ pmodel_env = { :host => host,
44
+ :path => path,
45
+ :user_id => user_id}
46
+ persist_model = {:name => model_name, :env => pmodel_env, :key_fields => key_fields}
47
+
48
+ #final env model
49
+ env = { :node_class_id => node_class_id,
50
+ :data_model => data_model,
51
+ :persist_model => persist_model }
52
+ end
53
+ end
54
+ #for testing CouchRest model
55
+
56
+ module NodeHelpers
57
+ DefaultNodeParams = {:my_category => 'default',
58
+ :parent_categories => ['default_parent'],
59
+ :description => 'default description'}
60
+
61
+ def get_default_params
62
+ DefaultNodeParams.dup #to avoid a couchrest weirdness don't use the params directly
63
+ end
64
+
65
+ def make_doc_no_attachment(user_class, override_defaults={})
66
+ init_params = get_default_params.merge(override_defaults)
67
+ return user_class.new(init_params)
68
+ end
69
+
70
+ def make_doc_w_attach_from_file(user_class, att_fname, override_defaults={})
71
+ test_filename = att_fname
72
+ test_basename = File.basename(test_filename)
73
+ raise "can't find file #{test_filename.inspect}" unless File.exists?(test_filename)
74
+ new_doc = make_doc_no_attachment(user_class, override_defaults)
75
+ new_doc.__save #doc must be saved before we can attach
76
+ file_data = {:src_filename => test_filename}
77
+ new_doc.files_add(file_data)
78
+ #new_doc.add_data_file(test_filename)
79
+ return new_doc
80
+ end
81
+ end
@@ -0,0 +1,15 @@
1
+ require "fileutils"
2
+
3
+ dirs_to_clean = ["/media-ec2/ec2a/projects/bufs/sandbox_for_specs/bufs_file_view_maker_spec/SampleCouchUser001",
4
+ "/media-ec2/ec2a/projects/bufs/sandbox_for_specs/bufs_file_view_maker_spec/SampleCouchUser002",
5
+ "/media-ec2/ec2a/projects/bufs/sandbox_for_specs/sample_data/SampleFileSysUser003/aa",
6
+ "/media-ec2/ec2a/projects/bufs/sandbox_for_specs/sample_data/SampleFileSysUser003/b",
7
+ "/media-ec2/ec2a/projects/bufs/sandbox_for_specs/sample_data/SampleFileSysUser003/c",
8
+ "/media-ec2/ec2a/projects/bufs/sandbox_for_specs/sample_data/SampleFileSysUser004/aa",
9
+ "/media-ec2/ec2a/projects/bufs/sandbox_for_specs/sample_data/SampleFileSysUser004/b",
10
+ "/media-ec2/ec2a/projects/bufs/sandbox_for_specs/sample_data/SampleFileSysUser004/c"]
11
+
12
+ dirs_to_clean.each do |dir|
13
+ FileUtils.rm_rf(dir)
14
+ end
15
+
@@ -0,0 +1,45 @@
1
+ #require helper for cleaner require statements
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../../lib/tinkit')
3
+
4
+ require 'couchrest'
5
+
6
+ require Tinkit.fixtures 'bufs_fixtures'
7
+ require Tinkit.helpers 'tk_escape'
8
+
9
+ doc_db_name = "http://127.0.0.1:5984/tk_escape_spec/"
10
+ EscapeTestDB = CouchRest.database!(doc_db_name)
11
+ EscapeTestDB.compact!
12
+
13
+ describe TkEscape do
14
+
15
+ before(:each) do
16
+ EscapeTestDB.recreate!
17
+ end
18
+
19
+ it "should escape and unescape properly to the database" do
20
+ #set initial conditions
21
+ test_file_name = TinkitFixtures.test_files['strange_characters_in_file_name']
22
+ test_file_basename = File.basename(test_file_name)
23
+ test_file_data = File.open(test_file_name) {|f| f.read}
24
+ test_doc_params = {'_id' => 'test_doc'}
25
+ EscapeTestDB.save_doc(test_doc_params)
26
+ doc = EscapeTestDB.get(test_doc_params['_id'])
27
+ #test
28
+ att_name = TkEscape.escape(test_file_basename)
29
+ EscapeTestDB.put_attachment(doc, att_name, test_file_data)
30
+ #verify results
31
+ couchdb_name = EscapeTestDB.get(test_doc_params['_id'])['_attachments'].keys.first
32
+ att_name.should == couchdb_name
33
+
34
+ #test round trip
35
+ EscapeTestDB.delete_attachment(EscapeTestDB.get(test_doc_params['_id']), att_name)
36
+ EscapeTestDB.put_attachment(EscapeTestDB.get(test_doc_params['_id']), couchdb_name, test_file_data)
37
+ couchdb_name_rt1 = EscapeTestDB.get(test_doc_params['_id'])['_attachments'].keys.first
38
+
39
+ #verify results
40
+ att_name.should == couchdb_name_rt1
41
+
42
+ EscapeTestDB.delete_doc(EscapeTestDB.get(test_doc_params['_id']))
43
+ end
44
+ end
45
+
@@ -0,0 +1,250 @@
1
+ #require helper for cleaner require statements
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../lib/helpers/require_helper')
3
+ require Tinkit.glue 'mysql/mysql_files_mgr'
4
+
5
+ include MysqlInterface
6
+ GlueEnvMock = Struct.new(:model_key, :file_mgr_table)
7
+
8
+ describe FilesMgr, "Setup and intialization" do
9
+
10
+ before(:all) do
11
+
12
+ @glue_env_mock = GlueEnvMock.new("_id", "fake_file_table_name")
13
+ @node_key = :_id
14
+
15
+ file1_data = "Example File1\nJust some text"
16
+ file2_data = "Example File2\nJust some more text"
17
+ file1_fname = "/tmp/example_file1.txt"
18
+ file2_fname = "/tmp/example_file2.txt"
19
+ files = {file1_fname => file1_data, file2_fname => file2_data}
20
+ files.each do |fname, data|
21
+ File.open(fname, 'w'){|f| f.write(data)}
22
+ end
23
+ @file_datas = [{:src_filename => @file1_fname}, {:src_filename => file2_fname}]
24
+ @node1_data = {:_id => 'spec_test1', :data => 'stuff1'}
25
+ end
26
+
27
+ it "should initialize" do
28
+
29
+ #we're not creating the table yet, as that depends on the glue and user
30
+ node_key_value = @node1_data[@node_key]
31
+ attach_handler = FilesMgr.new(@glue_env_mock, node_key_value)
32
+
33
+ #note actual table is setup in glue_env, not file_mgr
34
+ attach_handler.file_table_name.should == @glue_env_mock.file_mgr_table
35
+ end
36
+ end
37
+
38
+ describe FilesMgr, "Basic Operations" do
39
+ before(:all) do
40
+ @file_table_name = "attachment_spec__node_loc"
41
+ @file1_fname = "/tmp/example_file1.txt"
42
+ @file2_fname = "/tmp/example_file2.txt"
43
+ f1_bname = File.basename(@file1_fname)
44
+ f2_bname = File.basename(@file2_fname)
45
+ @file_stored_data = { f1_bname => File.open(@file1_fname, 'rb'){|f| f.read},
46
+ f2_bname =>File.open(@file2_fname, 'rb'){|f| f.read} }
47
+
48
+ @mock_key = :_id
49
+ @nodeMockClass = Struct.new(@mock_key, :my_GlueEnv)
50
+
51
+ @glue_env_mock = GlueEnvMock.new(@mock_key.to_s,
52
+ @file_table_name)
53
+
54
+ #set up table for spec
55
+
56
+ primary_key = '__pkid-file'
57
+ home_dir = ENV["HOME"]
58
+ my_pw = File.open("#{home_dir}/.locker/tinkit_mysql"){|f| f.read}.strip
59
+ @dbh = DBI.connect("DBI:Mysql:tinkit:localhost", "tinkit", my_pw)
60
+
61
+ sql = "CREATE TABLE IF NOT EXISTS `#{@file_table_name}` (
62
+ `#{primary_key}` INT NOT NULL AUTO_INCREMENT,
63
+ node_name VARCHAR(255),
64
+ basename VARCHAR(255) NOT NULL,
65
+ content_type VARCHAR(255),
66
+ modified_at VARCHAR(255),
67
+ raw_content LONGBLOB,
68
+ PRIMARY KEY (`#{primary_key}`),
69
+ UNIQUE KEY (node_name, basename) )"
70
+ @dbh.do(sql)
71
+ #
72
+ @file_datas = [{:src_filename => @file1_fname}, {:src_filename => @file2_fname}]
73
+ end
74
+
75
+
76
+ before(:each) do
77
+ @node1_data = {:_id => 'spec_test1', :data => 'stuff1'}
78
+ @node_mock = @nodeMockClass.new(@node1_data[@mock_key],
79
+ @glue_env_mock)
80
+
81
+ node_key_value = @node1_data[@node_key]
82
+ @attach_handler = FilesMgr.new(@glue_env_mock, node_key_value)
83
+ #@attach_handler.subtract_files(nil, :all)
84
+ end
85
+
86
+ after(:all) do
87
+ sql = "DROP TABLE `#{@file_table_name}`"
88
+ @dbh.do(sql)
89
+ end
90
+
91
+ it "should add and retrieve files" do
92
+ node = @node_mock
93
+
94
+ @file_datas.each do |file_data|
95
+ file_basename = File.basename(file_data[:src_filename])
96
+ data = @attach_handler.get_raw_data(node, file_basename)
97
+ data.should be_nil
98
+ end
99
+
100
+ #Add the Files
101
+ @attach_handler.add(node, @file_datas)
102
+
103
+ #Get the files and verify data
104
+ @file_datas.each do |file_data|
105
+ file_basename = File.basename(file_data[:src_filename])
106
+ data = @attach_handler.get_raw_data(node, file_basename)
107
+ data.should == @file_stored_data[file_basename]
108
+ end
109
+ end
110
+
111
+ it "should list attachment files" do
112
+ files = @attach_handler.list(@node_mock)
113
+ files.sort.should == @file_stored_data.keys.sort
114
+ end
115
+
116
+ it "should list metadata" do
117
+
118
+ md = @attach_handler.get_attachments_metadata(@node_mock)
119
+ md.should_not == nil
120
+ @file_datas.each do |file_data|
121
+ file_basename = File.basename(file_data[:src_filename])
122
+ each_md = md[file_basename]
123
+ each_md.should_not == nil
124
+ each_md.keys.should include :content_type
125
+ each_md.keys.should include :file_modified
126
+
127
+ file_basename = File.basename(file_data[:src_filename])
128
+ md[file_basename][:content_type].should =~ /^text\/plain/
129
+ time_str = md[file_basename][:file_modified]
130
+ Time.parse(time_str).should > Time.now - 1 #should have been modified less than a second ago
131
+ end
132
+ end
133
+
134
+ it "should be well behaved adding more files" do
135
+ node = @node_mock
136
+
137
+ #Get the original files and verify data
138
+ @file_datas.each do |file_data|
139
+ file_basename = File.basename(file_data[:src_filename])
140
+ data = @attach_handler.get_raw_data(node, file_basename)
141
+ data.should == @file_stored_data[file_basename]
142
+ end
143
+
144
+ #create some more files
145
+ file1_data = "Example File1\nNEW!! text"
146
+ file3_data = "Example File3\nYet more text"
147
+ file4_data = "Example File4\nand more text"
148
+ file3_fname = "/tmp/example_file3.txt"
149
+ file4_fname = "/tmp/example_file4.txt"
150
+ files = {@file1_fname => file1_data, file3_fname => file3_data, file4_fname => file4_data}
151
+ files.each do |fname, data|
152
+ File.open(fname, 'w'){|f| f.write(data)}
153
+ end
154
+ file1_data.should == File.open(@file1_fname){|f| f.read}
155
+ @file_datas2 = [{:src_filename => @file1_fname},
156
+ {:src_filename => file3_fname},
157
+ {:src_filename => file4_fname}]
158
+
159
+ #add them
160
+ @attach_handler.add(node, @file_datas2)
161
+
162
+ #Check the unchanged file (file2)
163
+ file2_basename = File.basename(@file2_fname)
164
+ data2 = @attach_handler.get_raw_data(node, file2_basename)
165
+ data2.should == @file_stored_data[file2_basename]
166
+
167
+ #Get the changed files and verify it is the new data
168
+ file1_basename = File.basename(@file1_fname)
169
+ data1 = @attach_handler.get_raw_data(node, file1_basename)
170
+ data1.should == file1_data
171
+
172
+ file3_basename = File.basename(file3_fname)
173
+ data3 = @attach_handler.get_raw_data(node, file3_basename)
174
+ data3.should == file3_data
175
+
176
+ file4_basename = File.basename(file4_fname)
177
+ data4 = @attach_handler.get_raw_data(node, file4_basename)
178
+ data4.should == file4_data
179
+ end
180
+
181
+ it "should delete (subtract) files" do
182
+ node = @node_mock
183
+ files_to_delete = [@file1_fname, @file2_fname]
184
+ #they should exist in the node
185
+ files_to_delete.each do |fname|
186
+ file_basename = File.basename(fname)
187
+ data = @attach_handler.get_raw_data(node, file_basename)
188
+ data.should match /^Example File/
189
+ end
190
+
191
+ basenames_to_delete = files_to_delete.map{|f| File.basename(f)}
192
+ @attach_handler.subtract(node, basenames_to_delete)
193
+
194
+ files_to_delete.each do |fname|
195
+ file_basename = File.basename(fname)
196
+ data = @attach_handler.get_raw_data(node, file_basename)
197
+ data.should be_nil
198
+ end
199
+ end
200
+
201
+ it "should add attachments from the raw data" do
202
+ node = @node_mock
203
+
204
+ raw_data = "Example File3\nYet more text"
205
+ content_type = "text/plain"
206
+ modified_at = Time.now.to_s
207
+ att_name = "example_raw_data.txt"
208
+
209
+ #Add the Raw Data
210
+ @attach_handler.add_raw_data(node, att_name, content_type, raw_data, modified_at)
211
+
212
+ #Get the files and verify data
213
+
214
+ data = @attach_handler.get_raw_data(node, att_name)
215
+ md = @attach_handler.get_attachments_metadata(node)[att_name]
216
+
217
+ data.should == raw_data
218
+ md[:content_type].should == content_type
219
+ md[:file_modified].should == modified_at
220
+ end
221
+
222
+ it "should delete all (subtract_all) files" do
223
+ node = @node_mock
224
+
225
+ #create some more attachments
226
+ del_data = {}
227
+ del_data["del_data1"] = "my life will be short"
228
+ del_data["del_data2"] = "alas too short"
229
+
230
+ #add the attachments
231
+ del_data.each do |name, data|
232
+ @attach_handler.add_raw_data(node, name, "text/plain", data, Time.now.to_s)
233
+ end
234
+
235
+ #verify it's there
236
+ del_data.each do |name, data|
237
+ stored_data = @attach_handler.get_raw_data(node, name)
238
+ stored_data.should == data
239
+ end
240
+
241
+ #delete it all
242
+ @attach_handler.subtract(node, :all)
243
+
244
+ #verify it's not there
245
+ del_data.each do |name, data|
246
+ stored_data = @attach_handler.get_raw_data(node, name)
247
+ stored_data.should be_nil
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,214 @@
1
+ #require helper for cleaner require statements
2
+ require File.join(File.expand_path(File.dirname(__FILE__)), '../lib/helpers/require_helper')
3
+
4
+ require Tinkit.glue 'mysql_glue_env'
5
+
6
+
7
+
8
+ describe MysqlEnv::GlueEnv, "Initialization" do
9
+
10
+ before(:each) do
11
+ #host is the database
12
+ persist_env = {:host => nil, :path => 'test_domain', :user_id => 'init_test_user'}
13
+ @persist_env = {:name => 'mysql_glue_test', :env => persist_env}
14
+ key_fields = {:required_keys => [:my_id],
15
+ :primary_key => :my_id }
16
+ @data_model_bindings = {:key_fields => key_fields, :views => nil}
17
+ end
18
+
19
+ it "should initialize properly" do
20
+ mysql_glue_obj = MysqlEnv::GlueEnv.new(@persist_env, @data_model_bindings)
21
+ mysql_glue_obj.dbh.connected?.should == true
22
+
23
+ mysql_glue_obj.user_id.should == @persist_env[:env][:user_id]
24
+ mysql_glue_obj.required_instance_keys.should == @data_model_bindings[:key_fields][:required_keys]
25
+ mysql_glue_obj.required_save_keys.should == @data_model_bindings[:key_fields][:required_keys]
26
+ mysql_glue_obj.node_key.should == @data_model_bindings[:key_fields][:primary_key]
27
+ mysql_glue_obj.metadata_keys.should == [mysql_glue_obj.persist_layer_key,
28
+ mysql_glue_obj.version_key,
29
+ mysql_glue_obj.namespace_key]
30
+ path = @persist_env[:env][:path]
31
+ mysql_glue_obj.user_datastore_location.should == "#{path}__#{mysql_glue_obj.user_id}"
32
+ mysql_glue_obj._files_mgr_class.class.should_not == nil #temp test
33
+ #sdb_glue_obj.views.should_not == nil #temp test
34
+ #sdb_glue_obj.moab_data.should_not == nil #temp test
35
+ end
36
+ end
37
+
38
+ describe MysqlEnv::GlueEnv, "Persistent Layer Basic Operations" do
39
+
40
+ before(:each) do
41
+ env = {:host => nil, :path => 'test_domain', :user_id => 'init_test_user'}
42
+ @persist_env = {:env => env}
43
+ key_fields = {:required_keys => [:my_id],
44
+ :primary_key => :my_id }
45
+ @data_model_bindings = {:key_fields => key_fields, :views => nil}
46
+ @mysql_glue_obj = MysqlEnv::GlueEnv.new(@persist_env, @data_model_bindings)
47
+ end
48
+
49
+ after(:each) do
50
+ table = @mysql_glue_obj.model_save_params[:table]
51
+ dbh = @mysql_glue_obj.model_save_params[:dbh]
52
+ sql = "DROP TABLE `#{table}`"
53
+ dbh.do(sql)
54
+ end
55
+
56
+ it "should persist data and be able to retrieve it" do
57
+ @mysql_glue_obj.should_not == nil
58
+ #:id was defined as the primary key
59
+ data1 = {:my_id => "test_id1", :data => "test data"}
60
+ empty_data = @mysql_glue_obj.get(data1[:my_id]) #hasn't been saved yet
61
+ empty_data.should == nil
62
+ @mysql_glue_obj.save(data1)
63
+ #Don't use native get_attributes, use obj's get, it will block until save is finished
64
+ persisted_data = @mysql_glue_obj.get(data1[:my_id])
65
+ persisted_data.should_not == nil
66
+ #p persisted_data
67
+ persisted_data[:my_id].should == data1[:my_id]
68
+ persisted_data[:data].should == data1[:data]
69
+ end
70
+
71
+ it "should be able to delete data" do
72
+ data1 = {:my_id => "test_id1", :data => "test data1"}
73
+ data2 = {:my_id => "test_id2", :data => "test data2"}
74
+ @mysql_glue_obj.save(data1)
75
+ @mysql_glue_obj.save(data2)
76
+ persisted_data1 = @mysql_glue_obj.get(data1[:my_id])
77
+ persisted_data2 = @mysql_glue_obj.get(data2[:my_id])
78
+ persisted_data1[:data].should == "test data1"
79
+ persisted_data2[:data].should == "test data2"
80
+ @mysql_glue_obj.destroy_node({:my_id => data2[:my_id]})
81
+ persisted_data1 = @mysql_glue_obj.get(data1[:my_id])
82
+ persisted_data2 = @mysql_glue_obj.get(data2[:my_id])
83
+ persisted_data1[:data].should == "test data1"
84
+ persisted_data2.should == nil
85
+ end
86
+ end
87
+
88
+ describe MysqlEnv::GlueEnv, "Persistent Layer Collection Operations" do
89
+
90
+ before(:each) do
91
+ env = {:host => nil, :path => 'test_domain', :user_id => 'init_test_user'}
92
+ @persist_env = {:env => env}
93
+ key_fields = {:required_keys => [:my_id],
94
+ :primary_key => :my_id }
95
+ @data_model_bindings = {:key_fields => key_fields, :views => nil}
96
+ @mysql_glue_obj = MysqlEnv::GlueEnv.new(@persist_env, @data_model_bindings)
97
+ end
98
+
99
+ after(:each) do
100
+ table = @mysql_glue_obj.model_save_params[:table]
101
+ dbh = @mysql_glue_obj.model_save_params[:dbh]
102
+ sql = "DROP TABLE `#{table}`"
103
+ dbh.do(sql)
104
+ end
105
+
106
+ it "should be able to query all" do
107
+ data1 = {:my_id => "test_id1", :data => "test data1"}
108
+ data2 = {:my_id => "test_id2", :data => "test data2"}
109
+ @mysql_glue_obj.save(data1)
110
+ @mysql_glue_obj.save(data2)
111
+
112
+ results = @mysql_glue_obj.query_all
113
+ #results.should == 'blah'
114
+ results.each do |raw_data|
115
+ case raw_data[:my_id]
116
+ when "test_id1"
117
+ raw_data[:data].should == "test data1"
118
+ when "test_id2"
119
+ raw_data[:data].should == "test data2"
120
+ else
121
+ raise "Unknown dataset"
122
+ end#case
123
+ end#each
124
+ end
125
+
126
+ it "should be able to find matching data" do
127
+ data1 = {:my_id => "test_id1", :data => "test data1", :tags => ['a', 'b', 'c']}
128
+ data2 = {:my_id => "test_id2", :data => "test data2", :tags => ['c', 'd', 'e']}
129
+ data3 = {:my_id => "test_id3", :data => "test data2", :tags => ['c', 'b', 'z']}
130
+ data_list = [data1, data2, data3]
131
+ data_list.each {|data| @mysql_glue_obj.save(data)}
132
+
133
+ result1 = @mysql_glue_obj.find_nodes_where(:my_id, :equals, "test_id1")
134
+ result1.size.should == 1
135
+ result1.first[:my_id].should == "test_id1"
136
+
137
+ result2 = @mysql_glue_obj.find_nodes_where(:my_id, :equals, "oops")
138
+ result2.should be_empty
139
+
140
+ result3 = @mysql_glue_obj.find_nodes_where(:data, :equals, "test data2")
141
+ result3.size.should == 2
142
+ ["test_id2", "test_id3"].should include result3.first[:my_id]
143
+ ["test_id2", "test_id3"].should include result3.last[:my_id]
144
+
145
+ result4 = @mysql_glue_obj.find_nodes_where(:tags, :equals, ['c', 'd', 'e'])
146
+ result4.size.should == 1
147
+ result4.first[:my_id].should == "test_id2"
148
+ end
149
+
150
+ it "should be able to find containting data" do
151
+ data1 = {:my_id => "test_id1", :data => "test data1", :tags => ['a', 'b', 'c']}
152
+ data2 = {:my_id => "test_id2", :data => "test data2", :tags => ['c', 'd', 'e']}
153
+ data3 = {:my_id => "test_id3", :data => "test data2", :tags => ['c', 'b', 'z']}
154
+ data_list = [data1, data2, data3]
155
+ data_list.each {|data| @mysql_glue_obj.save(data)}
156
+
157
+ result1 = @mysql_glue_obj.find_nodes_where(:my_id, :contains, "test_id2")
158
+ result1.size.should == 1
159
+ result1.first[:my_id].should == "test_id2"
160
+
161
+ result2 = @mysql_glue_obj.find_nodes_where(:tags, :contains, "c")
162
+ result2.size.should == 3
163
+
164
+ result3 = @mysql_glue_obj.find_nodes_where(:tags, :contains, "b")
165
+ result3.size.should == 2
166
+ ["test_id1", "test_id3"].should include result3.first[:my_id]
167
+ ["test_id1", "test_id3"].should include result3.last[:my_id]
168
+
169
+ result4 = @mysql_glue_obj.find_nodes_where(:tags, :contains, "oops")
170
+ result4.should be_empty
171
+ end
172
+
173
+ it "should be able to delete in bulk" do
174
+ data1 = {:my_id => "test_id1", :data => "delete me"}
175
+ data2 = {:my_id => "test_id2", :data => "keep me"}
176
+ data3 = {:my_id => "test_id3", :data => "delete me too"}
177
+ @mysql_glue_obj.save(data1)
178
+ @mysql_glue_obj.save(data2)
179
+ @mysql_glue_obj.save(data3)
180
+
181
+ results = @mysql_glue_obj.query_all
182
+ results.each do |raw_data|
183
+ case raw_data[:my_id]
184
+ when "test_id1"
185
+ raw_data[:data].should == "delete me"
186
+ when "test_id2"
187
+ raw_data[:data].should == "keep me"
188
+ when "test_id3"
189
+ raw_data[:data].should == "delete me too"
190
+ else
191
+ raise "Unknown dataset"
192
+ end#case
193
+ end#each
194
+
195
+ raw_rcds_to_delete = [data1, data3]
196
+ @mysql_glue_obj.destroy_bulk(raw_rcds_to_delete)
197
+
198
+ results = @mysql_glue_obj.query_all
199
+ #puts "Destroy Bulk results: #{results.inspect}"
200
+ results.each do |raw_data|
201
+ case raw_data[:my_id]
202
+ when "test_id1"
203
+ raise "Oops should have been deleted"
204
+ when "test_id2"
205
+ raw_data[:data].should == "keep me"
206
+ when "test_id3"
207
+ raise "Oops should have been deleted"
208
+ else
209
+ raise "Unknown dataset"
210
+ end#case
211
+ end#each
212
+ end#it
213
+ end
214
+