sqlite_magic 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/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,11 @@
1
+ language: ruby
2
+ rvm:
3
+ # - "1.8.7"
4
+ - "1.9.2"
5
+ - "1.9.3"
6
+ - jruby-18mode # JRuby in 1.8 mode
7
+ - jruby-19mode # JRuby in 1.9 mode
8
+ # - rbx-18mode
9
+ - rbx-19mode
10
+ # uncomment this line if your project needs to run something other than `rake`:
11
+ script: bundle exec rspec spec
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in sqlite_magic.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Chris Taggart
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,32 @@
1
+ # SqliteMagic
2
+ [![Build Status](https://travis-ci.org/openc/sqlite_magic.png)](https://travis-ci.org/openc/sqlite_magic)
3
+ Experimental abstraction and refactoring of sqlite utility methods from
4
+ scraperwiki-ruby gem
5
+ Note: Not all functionality has yet been duplicated, and this may not work for
6
+ you. Developed and tested on Ruby 1.9.3
7
+
8
+ ## Installation
9
+
10
+ Add this line to your application's Gemfile:
11
+
12
+ gem 'sqlite_magic', :git => 'git@github.com:openc/sqlite_magic.git'
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install sqlite_magic
21
+
22
+ ## Usage
23
+
24
+ TODO: Write usage instructions here
25
+
26
+ ## Contributing
27
+
28
+ 1. Fork it
29
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
30
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
31
+ 4. Push to the branch (`git push origin my-new-feature`)
32
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,168 @@
1
+ require 'sqlite_magic/version'
2
+ require 'sqlite3'
3
+
4
+ module SqliteMagic
5
+
6
+ extend self
7
+
8
+ class Error < StandardError;end
9
+ class DatabaseError < Error;end
10
+ class NoSuchTable < Error;end
11
+
12
+ class Connection
13
+ attr_reader :database
14
+ def initialize(db_loc='sqlite.db')
15
+ @database = SQLite3::Database.new(db_loc)
16
+ end
17
+
18
+ def add_columns(tbl_name, col_names)
19
+ existing_cols = database.table_info(tbl_name).map{ |c| c['name'] }
20
+ missing_cols = col_names.map(&:to_s) - existing_cols
21
+ missing_cols.each do |col_name|
22
+ database.execute("ALTER TABLE #{tbl_name} ADD COLUMN #{col_name}")
23
+ end
24
+ end
25
+
26
+ def close
27
+ database.close
28
+ end
29
+
30
+ def commit
31
+ database.commit
32
+ end
33
+
34
+ def create_table(tbl_name, col_names, unique_keys=nil)
35
+ puts "Now creating new table: #{tbl_name}" if verbose?
36
+ query = unique_keys ? "CREATE TABLE #{tbl_name} (#{col_names.join(',')}, UNIQUE (#{unique_keys.join(',')}))" :
37
+ "CREATE TABLE #{tbl_name} (#{col_names.join(',')})"
38
+ database.execute query
39
+ end
40
+
41
+ def execute(query,data=nil)
42
+ raw_response = data ? database.execute2(query, data) : database.execute2(query)
43
+ keys = raw_response.shift # get the keys
44
+ raw_response.map{|e| Hash[keys.zip(e)] }
45
+ end
46
+
47
+ # This is an (expensive) convenience method to insert a row (for given unique keys), or if the row already exists
48
+ #
49
+ def insert_or_update(uniq_keys, values_hash, tbl_name='ocdata')
50
+ field_names_as_symbol_string = values_hash.keys.map{ |k| ":#{k}" }.join(',') # need to appear as symbols
51
+
52
+ sql_statement = "INSERT INTO #{tbl_name} (#{values_hash.keys.join(',')}) VALUES (#{field_names_as_symbol_string})"
53
+ database.execute(sql_statement, values_hash)
54
+ rescue SQLite3::ConstraintException => e
55
+ unique_key_constraint = uniq_keys.map { |k| "#{k}=:#{k}" }.join(' AND ')
56
+ update_keys = (values_hash.keys - uniq_keys).map { |k| "#{k}=:#{k}" }.join(', ')
57
+ sql_statement = "UPDATE #{tbl_name} SET #{update_keys} WHERE #{unique_key_constraint}"
58
+ database.execute sql_statement, values_hash
59
+ rescue SQLite3::SQLException => e
60
+ puts "Exception (#{e.inspect}) raised: #{sql_statement}" if verbose?
61
+ # defer to save_data, which can handle missing tables, columns etc
62
+ save_data(uniq_keys, values_hash, tbl_name)
63
+ end
64
+
65
+ # #save data into the database
66
+ def save_data(uniq_keys, values_array, tbl_name)
67
+ values_array = [values_array].flatten(1) # coerce to an array
68
+ all_field_names = values_array.map(&:keys).flatten.uniq
69
+ all_field_names_as_string = all_field_names.join(',')
70
+ all_field_names_as_symbol_string = all_field_names.map{ |k| ":#{k}" }.join(',') # need to appear as symbols
71
+ begin
72
+ values_array.each do |values_hash|
73
+ # mustn't use nil value in unique value due to fact that SQLite considers NULL values to be different from
74
+ # each other in UNIQUE indexes. See http://www.sqlite.org/lang_createindex.html
75
+ raise DatabaseError.new("Data has nil value for unique key. Unique keys are #{uniq_keys}. Offending data: #{values_hash.inspect}") unless uniq_keys.all?{ |k| values_hash[k] }
76
+ sql_query = "INSERT OR REPLACE INTO #{tbl_name} (#{all_field_names_as_string}) VALUES (#{all_field_names_as_symbol_string})"
77
+ database.execute(sql_query, values_hash)
78
+ end
79
+ rescue SQLite3::SQLException => e
80
+ puts "Exception (#{e.inspect}) raised" if verbose?
81
+ case e.message
82
+ when /no such table/
83
+ create_table(tbl_name, all_field_names, uniq_keys)
84
+ retry
85
+ when /has no column/
86
+ add_columns(tbl_name, all_field_names)
87
+ retry
88
+ else
89
+ raise e
90
+ end
91
+ end
92
+ end
93
+
94
+ # Convenience method that returns true if VERBOSE environmental variable set (at the moment whatever it is set to)
95
+ def verbose?
96
+ ENV['VERBOSE']
97
+ end
98
+
99
+ # def buildinitialtable(data)
100
+ # raise "buildinitialtable: no swdatakeys" unless @swdatakeys.length == 0
101
+ # coldef = self.newcolumns(data)
102
+ # raise "buildinitialtable: no coldef" unless coldef.length > 0
103
+ # # coldef = coldef[:1] # just put one column in; the rest could be altered -- to prove it's good
104
+ # scoldef = coldef.map { |col| format("`%s` %s", col[0], col[1]) }.join(",")
105
+ # @db.execute(format("create table main.`%s` (%s)", @swdatatblname, scoldef))
106
+ # end
107
+ # def addnewcolumn(k, vt)
108
+ # @db.execute(format("alter table main.`%s` add column `%s` %s", @swdatatblname, k, vt))
109
+ # end
110
+ # Internal function to check a row of data, convert to right format
111
+ # def ScraperWiki._convdata(unique_keys, scraper_data)
112
+ # if unique_keys
113
+ # for key in unique_keys
114
+ # if !key.kind_of?(String) and !key.kind_of?(Symbol)
115
+ # raise 'unique_keys must each be a string or a symbol, this one is not: ' + key
116
+ # end
117
+ # if !scraper_data.include?(key) and !scraper_data.include?(key.to_sym)
118
+ # raise 'unique_keys must be a subset of data, this one is not: ' + key
119
+ # end
120
+ # if scraper_data[key] == nil and scraper_data[key.to_sym] == nil
121
+ # raise 'unique_key value should not be nil, this one is nil: ' + key
122
+ # end
123
+ # end
124
+ # end
125
+ #
126
+ # jdata = { }
127
+ # scraper_data.each_pair do |key, value|
128
+ # raise 'key must not have blank name' if not key
129
+ #
130
+ # key = key.to_s if key.kind_of?(Symbol)
131
+ # raise 'key must be string or symbol type: ' + key if key.class != String
132
+ # raise 'key must be simple text: ' + key if !/[a-zA-Z0-9_\- ]+$/.match(key)
133
+ #
134
+ # # convert formats
135
+ # if value.kind_of?(Date)
136
+ # value = value.iso8601
137
+ # end
138
+ # if value.kind_of?(Time)
139
+ # # debugger
140
+ # value = value.utc.iso8601
141
+ # raise "internal error, timezone came out as non-UTC while converting to SQLite format" unless value.match(/([+-]00:00|Z)$/)
142
+ # value.gsub!(/([+-]00:00|Z)$/, '')
143
+ # end
144
+ # if ![Fixnum, Float, String, TrueClass, FalseClass, NilClass].include?(value.class)
145
+ # value = value.to_s
146
+ # end
147
+ #
148
+ # jdata[key] = value
149
+ # end
150
+ # return jdata
151
+ # end
152
+ end
153
+
154
+
155
+ # When deciding on the location of the SQLite databases we need to set the directory relative to the directory
156
+ # of the file/app that includes the gem, not the gem itself.
157
+ # Doing it this way, and setting a class variable feels ugly, but this appears to be difficult in Ruby, esp as the
158
+ # file may ultimately be called by another process, e.g. the main OpenCorporates app or the console, whose main
159
+ # directory is unrelated to where the databases are stored (which means we can't use Dir.pwd etc). The only time
160
+ # we know about the directory is when the module is called to extend the file, and we capture that in the
161
+ # @app_directory class variable
162
+ # def self.extended(obj)
163
+ # path, = caller[0].partition(":")
164
+ # @@app_directory = File.dirname(path)
165
+ # end
166
+
167
+ end
168
+
@@ -0,0 +1,3 @@
1
+ module SqliteMagic
2
+ VERSION = "0.0.1"
3
+ end
data/spec/.DS_Store ADDED
Binary file
@@ -0,0 +1,335 @@
1
+ require_relative '../spec_helper'
2
+ require 'sqlite_magic'
3
+
4
+ describe SqliteMagic do
5
+ it "should define SqliteMagicError exception as subclass of StandardError" do
6
+ SqliteMagic::Error.superclass.should be StandardError
7
+ end
8
+
9
+ it "should define DatabaseError exception as subclass of Error" do
10
+ SqliteMagic::DatabaseError.superclass.should be SqliteMagic::Error
11
+ end
12
+
13
+ it "should define InvalidDataError exception as subclass of Error" do
14
+ SqliteMagic::NoSuchTable.superclass.should be SqliteMagic::Error
15
+ end
16
+
17
+ describe SqliteMagic::Connection do
18
+ before do
19
+ @dummy_db = stub('dummy_sqlite3_database')
20
+ SQLite3::Database.stub(:new).and_return(@dummy_db)
21
+ @connection = SqliteMagic::Connection.new
22
+ end
23
+
24
+ describe "initialisation" do
25
+ it "should return a type of connection" do
26
+ connection = SqliteMagic::Connection.new
27
+ connection.should be_kind_of SqliteMagic::Connection
28
+ end
29
+
30
+ it "should open up a Sqlite3 database with default name" do
31
+ SQLite3::Database.should_receive(:new).with('sqlite.db').and_return(@dummy_db)
32
+ connection = SqliteMagic::Connection.new
33
+ end
34
+
35
+ it "should use given db_name when setting up Sqlite3" do
36
+ SQLite3::Database.should_receive(:new).with('path/to/mynew.db').and_return(@dummy_db)
37
+ connection = SqliteMagic::Connection.new('path/to/mynew.db')
38
+ end
39
+
40
+ it "should store Sqlite3 database in @database instance variable" do
41
+ connection = SqliteMagic::Connection.new
42
+ connection.instance_variable_get(:@database).should == @dummy_db
43
+ end
44
+ end
45
+
46
+ it "should have #database accessor" do
47
+ SqliteMagic::Connection.new.database.should == @dummy_db
48
+ end
49
+
50
+ describe "#execute" do
51
+ before do
52
+ response_data = [['heading 1', 'heading 2', 'heading 3'],
53
+ ['some val 1', 'some val 2', 'some val 3'],
54
+ ['another val 1', 'another val 2', 'another val 3']]
55
+ @dummy_db.stub(:execute2).and_return(response_data)
56
+ end
57
+
58
+ it "should use #execute2 to run query on database" do
59
+ @dummy_db.should_receive(:execute2).with('some query',[:foo])
60
+
61
+ @connection.execute('some query',[:foo])
62
+ end
63
+
64
+ it "should return array of hashes" do
65
+ result = @connection.execute('some query',[:foo])
66
+ result.should be_kind_of Array
67
+ result.first.should be_kind_of Hash
68
+ result.size.should == 2
69
+ end
70
+
71
+ it "should use map results to hash with headings as keys" do
72
+ result = @connection.execute('some query',[:foo])
73
+ result.first['heading 1'].should == 'some val 1'
74
+ end
75
+
76
+ context 'and only headings returned' do
77
+ it "should return empty array" do
78
+ @dummy_db.stub(:execute2).and_return([['foo1','foo2']])
79
+ @connection.execute('some query',[:foo]).should == []
80
+ end
81
+ end
82
+
83
+ context 'and nil passed as second argument' do
84
+ it "should not pass bind vars to #execute2" do
85
+ @dummy_db.should_receive(:execute2).with('some query')
86
+
87
+ @connection.execute('some query',nil)
88
+ end
89
+ end
90
+ end
91
+
92
+ describe '#save_data' do
93
+ before do
94
+ @connection = SqliteMagic::Connection.new
95
+ @data = [{:foo => 'bar', :foo2 => 'bar2', :foo3 => 'bar3'},
96
+ {:foo2 => 'baz2', :foo3 => 'baz3', :foo4 => 'baz4'}]
97
+ @unique_keys = [:foo2,:foo3]
98
+ @expected_query_1 = "INSERT OR REPLACE INTO foo_table (foo,foo2,foo3,foo4) VALUES (:foo,:foo2,:foo3,:foo4)"
99
+ @expected_query_2 = "INSERT OR REPLACE INTO foo_table (foo,foo2,foo3,foo4) VALUES (:foo,:foo2,:foo3,:foo4)"
100
+ end
101
+
102
+ it 'should insert each data hash using all given field names' do
103
+ @dummy_db.should_receive(:execute).with(@expected_query_1, @data[0])
104
+ @dummy_db.should_receive(:execute).with(@expected_query_2, @data[1])
105
+
106
+ @connection.save_data(@unique_keys, @data, 'foo_table')
107
+ end
108
+
109
+ context 'and datum is a single hash' do
110
+ it 'should save the hash' do
111
+ @expected_query_1 = "INSERT OR REPLACE INTO foo_table (foo,foo2,foo3) VALUES (:foo,:foo2,:foo3)"
112
+ @dummy_db.should_receive(:execute).with(@expected_query_1, @data.first)
113
+ @connection.save_data(@unique_keys, @data.first, 'foo_table')
114
+ end
115
+ end
116
+
117
+ context 'and table does not exist' do
118
+ before do
119
+ @dummy_db.stub(:execute) # default
120
+ # raise just once
121
+ @dummy_db.should_receive(:execute).with(@expected_query_1, @data[0]).
122
+ and_raise(SQLite3::SQLException.new("no such table: foo_table") )
123
+ end
124
+
125
+ it 'should create table using all field names and unique keys' do
126
+ @connection.should_receive(:create_table).with('foo_table', [:foo,:foo2,:foo3, :foo4], @unique_keys)
127
+ @connection.save_data(@unique_keys, @data, 'foo_table')
128
+ end
129
+
130
+ it 'should insert data' do
131
+ @connection.stub(:create_table)
132
+ @dummy_db.should_receive(:execute).with(@expected_query_2, @data[1])
133
+
134
+ @connection.save_data(@unique_keys, @data, 'foo_table')
135
+ end
136
+ end
137
+
138
+ context 'and some columns do not exist' do
139
+ before do
140
+ @dummy_db.stub(:execute) # default
141
+ # raise just once
142
+ @dummy_db.should_receive(:execute).with(@expected_query_1, @data[0]).
143
+ and_raise(SQLite3::SQLException.new("table mynewtable has no column named foo") )
144
+ end
145
+
146
+ it 'should create missing fields using all field names and unique keys' do
147
+ @connection.should_receive(:add_columns).with('foo_table', [:foo,:foo2,:foo3, :foo4])
148
+ @connection.save_data(@unique_keys, @data, 'foo_table')
149
+ end
150
+
151
+ it 'should insert data' do
152
+ @connection.stub(:add_columns)
153
+ @dummy_db.should_receive(:execute).with(@expected_query_2, @data[1])
154
+
155
+ @connection.save_data(@unique_keys, @data, 'foo_table')
156
+ end
157
+ end
158
+
159
+ context 'and some other error is raised' do
160
+ before do
161
+ @dummy_db.stub(:execute) # default
162
+ # raise just once
163
+ @dummy_db.should_receive(:execute).with(@expected_query_1, @data[0]).
164
+ and_raise(SQLite3::SQLException.new("something else has gone wrong") )
165
+ end
166
+
167
+ it 'should raise error' do
168
+ lambda { @connection.save_data(@unique_keys, @data, 'foo_table') }.should raise_error(SQLite3::SQLException)
169
+ @connection.save_data(@unique_keys, @data, 'foo_table')
170
+ end
171
+ end
172
+
173
+ context 'and data for unique keys is nil' do
174
+ it 'should raise DatabaseError' do
175
+ @data.first[:foo2] = nil
176
+ lambda { @connection.save_data(@unique_keys, @data, 'foo_table') }.should raise_error(SqliteMagic::DatabaseError, /unique key.*foo2/)
177
+ end
178
+ end
179
+ end
180
+
181
+ describe '#create_table' do
182
+ it 'should create default table using given field names' do
183
+ expected_query = "CREATE TABLE some_table (foo,bar,baz)"
184
+ @dummy_db.should_receive(:execute).with(expected_query)
185
+ @connection.create_table(:some_table, [:foo,:bar,:baz])
186
+ end
187
+
188
+ context 'and unique keys are given' do
189
+ it 'should add constraint for given keys' do
190
+ expected_query = "CREATE TABLE some_table (foo,bar,baz, UNIQUE (foo,baz))"
191
+ @dummy_db.should_receive(:execute).with(expected_query)
192
+ @connection.create_table(:some_table, [:foo,:bar,:baz], [:foo,:baz])
193
+ end
194
+ end
195
+ end
196
+
197
+ describe "add_columns" do
198
+ before do
199
+ @table_info = [{"cid"=>0, "name"=>"bar", "type"=>"", "notnull"=>0, "dflt_value"=>nil, "pk"=>0},
200
+ {"cid"=>1, "name"=>"rssd_id", "type"=>"", "notnull"=>0, "dflt_value"=>nil, "pk"=>0}]
201
+ end
202
+
203
+ it 'should get table info' do
204
+ @dummy_db.stub(:execute)
205
+ @dummy_db.should_receive(:table_info).with(:foo_table).and_return(@table_info)
206
+ @connection.add_columns(:foo_table, [:foo,:bar,:baz])
207
+ end
208
+
209
+ it 'should add columns that arent there already' do
210
+ @dummy_db.stub(:table_info).and_return(@table_info)
211
+ @dummy_db.should_receive(:execute).with('ALTER TABLE foo_table ADD COLUMN foo')
212
+ @dummy_db.should_receive(:execute).with('ALTER TABLE foo_table ADD COLUMN baz')
213
+ @connection.add_columns(:foo_table, [:foo,:bar,:baz])
214
+ end
215
+ end
216
+
217
+ describe '#insert_or_update' do
218
+ before do
219
+ @datum = {:foo => 'bar', :foo2 => 'bar2', :foo3 => 'bar3', :foo4 => 'bar4'}
220
+ @unique_keys = [:foo2,:foo3]
221
+ @expected_query = "INSERT INTO foo_table (foo,foo2,foo3,foo4) VALUES (:foo,:foo2,:foo3,:foo4)"
222
+ end
223
+
224
+ it 'should insert data' do
225
+ @dummy_db.should_receive(:execute).with(@expected_query, @datum)
226
+ @connection.insert_or_update(@unique_keys, @datum, 'foo_table')
227
+ end
228
+
229
+ it 'should not update data' do
230
+ @dummy_db.should_not_receive(:execute).with(/UPDATE/, anything)
231
+ @connection.insert_or_update(@unique_keys, @datum, 'foo_table')
232
+ end
233
+
234
+ context 'and no table name given' do
235
+ before do
236
+ @expected_query = "INSERT INTO ocdata (foo,foo2,foo3,foo4) VALUES (:foo,:foo2,:foo3,:foo4)"
237
+ end
238
+
239
+ it 'should use ocdata table by default' do
240
+ @dummy_db.should_receive(:execute).with(@expected_query, @datum)
241
+ @connection.insert_or_update(@unique_keys, @datum)
242
+ end
243
+ end
244
+
245
+ context 'and data already exists' do
246
+ before do
247
+ @dummy_db.should_receive(:execute).with(/INSERT/, anything).and_raise(SQLite3::ConstraintException.new('constraint failed'))
248
+ @expected_update_query = "UPDATE foo_table SET foo=:foo, foo4=:foo4 WHERE foo2=:foo2 AND foo3=:foo3"
249
+ end
250
+
251
+ it 'should update given columns dependent on unique keys' do
252
+ @dummy_db.should_receive(:execute).with(@expected_update_query, @datum)
253
+ @connection.insert_or_update(@unique_keys, @datum, 'foo_table')
254
+ end
255
+ context 'and no table name given' do
256
+ before do
257
+ @expected_update_query = "UPDATE ocdata SET foo=:foo, foo4=:foo4 WHERE foo2=:foo2 AND foo3=:foo3"
258
+ end
259
+
260
+ it 'should use ocdata table by default' do
261
+ @dummy_db.should_receive(:execute).with(@expected_update_query, @datum)
262
+ @connection.insert_or_update(@unique_keys, @datum)
263
+ end
264
+ end
265
+
266
+ end
267
+
268
+ context 'and SQLite3::SQLException raised' do
269
+ before do
270
+ @dummy_db.stub(:execute) # default
271
+ # raise just once
272
+ @dummy_db.should_receive(:execute).
273
+ and_raise(SQLite3::SQLException )
274
+ end
275
+
276
+ it 'should defer to save_data' do
277
+ @connection.stub(:create_table)
278
+ @connection.should_receive(:save_data).with(@unique_keys, @datum, 'foo_table')
279
+
280
+ @connection.insert_or_update(@unique_keys, @datum, 'foo_table')
281
+ end
282
+ end
283
+ end
284
+
285
+ describe '#verbose?' do
286
+ it 'should return false if ENV["VERBOSE"] not set' do
287
+ @connection.verbose?.should be_false
288
+ end
289
+
290
+ it 'should return false if ENV["VERBOSE"] set' do
291
+ ENV["VERBOSE"] = 'foo'
292
+ @connection.verbose?.should be_true
293
+ ENV["VERBOSE"] = nil # reset
294
+ end
295
+ end
296
+
297
+ describe '#close' do
298
+ it 'should close database' do
299
+ @dummy_db.should_receive(:close)
300
+ @connection.close
301
+ end
302
+ end
303
+
304
+ describe '#commit' do
305
+ it 'should send commit to database' do
306
+ @dummy_db.should_receive(:commit)
307
+ @connection.commit
308
+ end
309
+ end
310
+ end
311
+
312
+ # before do
313
+ # @dummy_db = stub('database_connection')
314
+ # SqliteMagic.stub(:database).and_return(@dummy_db)
315
+ # end
316
+
317
+
318
+ # describe '#database_file' do
319
+ # it 'should return file based on class and in db directory in working directory' do
320
+ # expected_file = File.expand_path(File.join(File.dirname(__FILE__),'..','db','foobot.db'))
321
+ # File.expand_path(SqliteMagic.database_file).should == expected_file
322
+ # end
323
+ # end
324
+
325
+ # end
326
+ #
327
+ # describe '#unlock_database' do
328
+ # it "should start and end transaction on database" do
329
+ # @dummy_db.should_receive(:execute).with('BEGIN TRANSACTION; END;')
330
+ # SqliteMagic.unlock_database
331
+ # end
332
+ # end
333
+ #
334
+
335
+ end
@@ -0,0 +1,5 @@
1
+ require 'rspec/autorun'
2
+ # require 'debugger'
3
+
4
+ RSpec.configure do |config|
5
+ end
@@ -0,0 +1,27 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'sqlite_magic/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "sqlite_magic"
8
+ spec.version = SqliteMagic::VERSION
9
+ spec.authors = ["Chris Taggart"]
10
+ spec.email = ["info@opencorporates.com"]
11
+ spec.description = %q{Sprinkles some magic onto Sqlite3 gem. Sort of extracted from Scraperwiki gem}
12
+ spec.summary = %q{Sprinkles some magic onto Sqlite3 gem}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency "sqlite3"
22
+
23
+ spec.add_development_dependency "bundler", "~> 1.3"
24
+ spec.add_development_dependency "rake"
25
+ spec.add_development_dependency "rspec"
26
+
27
+ end
metadata ADDED
@@ -0,0 +1,124 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: sqlite_magic
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Chris Taggart
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2013-07-03 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: sqlite3
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ">="
26
+ - !ruby/object:Gem::Version
27
+ segments:
28
+ - 0
29
+ version: "0"
30
+ type: :runtime
31
+ version_requirements: *id001
32
+ - !ruby/object:Gem::Dependency
33
+ name: bundler
34
+ prerelease: false
35
+ requirement: &id002 !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - ~>
38
+ - !ruby/object:Gem::Version
39
+ segments:
40
+ - 1
41
+ - 3
42
+ version: "1.3"
43
+ type: :development
44
+ version_requirements: *id002
45
+ - !ruby/object:Gem::Dependency
46
+ name: rake
47
+ prerelease: false
48
+ requirement: &id003 !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ segments:
53
+ - 0
54
+ version: "0"
55
+ type: :development
56
+ version_requirements: *id003
57
+ - !ruby/object:Gem::Dependency
58
+ name: rspec
59
+ prerelease: false
60
+ requirement: &id004 !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ segments:
65
+ - 0
66
+ version: "0"
67
+ type: :development
68
+ version_requirements: *id004
69
+ description: Sprinkles some magic onto Sqlite3 gem. Sort of extracted from Scraperwiki gem
70
+ email:
71
+ - info@opencorporates.com
72
+ executables: []
73
+
74
+ extensions: []
75
+
76
+ extra_rdoc_files: []
77
+
78
+ files:
79
+ - .gitignore
80
+ - .travis.yml
81
+ - Gemfile
82
+ - LICENSE.txt
83
+ - README.md
84
+ - Rakefile
85
+ - lib/sqlite_magic.rb
86
+ - lib/sqlite_magic/version.rb
87
+ - spec/.DS_Store
88
+ - spec/lib/sqlite_magic_spec.rb
89
+ - spec/spec_helper.rb
90
+ - sqlite_magic.gemspec
91
+ has_rdoc: true
92
+ homepage: ""
93
+ licenses:
94
+ - MIT
95
+ post_install_message:
96
+ rdoc_options: []
97
+
98
+ require_paths:
99
+ - lib
100
+ required_ruby_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ segments:
105
+ - 0
106
+ version: "0"
107
+ required_rubygems_version: !ruby/object:Gem::Requirement
108
+ requirements:
109
+ - - ">="
110
+ - !ruby/object:Gem::Version
111
+ segments:
112
+ - 0
113
+ version: "0"
114
+ requirements: []
115
+
116
+ rubyforge_project:
117
+ rubygems_version: 1.3.6
118
+ signing_key:
119
+ specification_version: 3
120
+ summary: Sprinkles some magic onto Sqlite3 gem
121
+ test_files:
122
+ - spec/.DS_Store
123
+ - spec/lib/sqlite_magic_spec.rb
124
+ - spec/spec_helper.rb