sqlite_magic 0.0.1

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