arc 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. data/.gitignore +9 -0
  2. data/.rspec +1 -0
  3. data/Gemfile +21 -0
  4. data/Rakefile +35 -0
  5. data/arc.gemspec +20 -0
  6. data/lib/arc.rb +13 -0
  7. data/lib/arc/casting.rb +66 -0
  8. data/lib/arc/data_stores.rb +9 -0
  9. data/lib/arc/data_stores/abstract/arel_compatibility.rb +50 -0
  10. data/lib/arc/data_stores/abstract/object_definitions.rb +55 -0
  11. data/lib/arc/data_stores/abstract/store.rb +55 -0
  12. data/lib/arc/data_stores/mysql/object_definitions.rb +54 -0
  13. data/lib/arc/data_stores/mysql/store.rb +51 -0
  14. data/lib/arc/data_stores/postgres/object_definitions.rb +70 -0
  15. data/lib/arc/data_stores/postgres/store.rb +38 -0
  16. data/lib/arc/data_stores/sqlite/object_definitions.rb +51 -0
  17. data/lib/arc/data_stores/sqlite/store.rb +43 -0
  18. data/lib/arc/quoting.rb +91 -0
  19. data/lib/arc/reactor.rb +29 -0
  20. data/lib/arc/version.rb +3 -0
  21. data/spec/casting_spec.rb +74 -0
  22. data/spec/data_stores/abstract/arel_compatibility_spec.rb +63 -0
  23. data/spec/data_stores/abstract/object_definitions_spec.rb +75 -0
  24. data/spec/data_stores/abstract/store_spec.rb +59 -0
  25. data/spec/data_stores/integration/crud_spec.rb +79 -0
  26. data/spec/data_stores/integration/schema_spec.rb +47 -0
  27. data/spec/data_stores/mysql/store_spec.rb +11 -0
  28. data/spec/data_stores/postgres/store_spec.rb +11 -0
  29. data/spec/data_stores/sqlite/store_spec.rb +11 -0
  30. data/spec/data_stores_spec.rb +15 -0
  31. data/spec/quoting_spec.rb +97 -0
  32. data/spec/spec_helper.rb +81 -0
  33. data/spec/support/config.yml +16 -0
  34. data/spec/support/resources/rails.png +0 -0
  35. data/spec/support/schemas/drop_mysql.sql +1 -0
  36. data/spec/support/schemas/drop_postgres.sql +1 -0
  37. data/spec/support/schemas/drop_sqlite.sql +1 -0
  38. data/spec/support/schemas/mysql.sql +10 -0
  39. data/spec/support/schemas/postgres.sql +12 -0
  40. data/spec/support/schemas/sqlite.sql +12 -0
  41. metadata +105 -0
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+ require 'arc/data_stores/abstract/object_definitions'
3
+
4
+ module Arc
5
+ module DataStores
6
+ module ObjectDefinitions
7
+ describe ObjectDefinitions do
8
+ before :each do
9
+ @store = AbstractDataStore.new ArcTest.config[:empty]
10
+ end
11
+
12
+ describe Schema do
13
+ it 'includes Collector' do
14
+ Schema.included_modules.should include(Collector)
15
+ end
16
+ it 'aliases item_names to table_names' do
17
+ schema = Schema.new nil
18
+ schema.should respond_to(:table_names)
19
+ end
20
+ end
21
+
22
+ describe Table do
23
+ it 'includes Collector' do
24
+ Table.included_modules.should include(Collector)
25
+ end
26
+ it 'aliases item_names to column_names' do
27
+ table = Table.new nil, :superheros
28
+ table.should respond_to(:column_names)
29
+ end
30
+ describe '#new' do
31
+ it 'has a name' do
32
+ Table.new('superheros').name.should == 'superheros'
33
+ end
34
+ it 'sets the data store' do
35
+ Table.new('superheros', @store).instance_variable_get(:@data_store).should be(@store)
36
+ end
37
+ end
38
+ end
39
+
40
+ describe "Column#new" do
41
+ it 'sets the datastore' do
42
+ c = Column.new @store
43
+ c.instance_variable_get(:@data_store).should be(@store)
44
+ end
45
+ it "sets the column's name" do
46
+ c = Column.new nil, :name => :superheros
47
+ c.name.should == :superheros
48
+ end
49
+ it "sets the column's allows_null" do
50
+ c = Column.new nil, :allows_null => false
51
+ c.allows_null?.should == false
52
+ end
53
+ it "sets the column's default value" do
54
+ c = Column.new nil, :default => "superman"
55
+ c.default.should == "superman"
56
+ end
57
+ it "sets the column's primary_key?" do
58
+ c = Column.new nil, :primary_key => true
59
+ c.pk?.should be_true
60
+ c.primary_key?.should be_true
61
+ end
62
+ it "sets the string representation of the column's type" do
63
+ c = Column.new nil, :type => "INTEGER"
64
+ c.instance_variable_get(:@stype).should == "INTEGER"
65
+ end
66
+ it 'throws NotImplementedError when querying type' do
67
+ c = Column.new nil
68
+ ->{ c.type }.should raise_error(NotImplementedError)
69
+ end
70
+ end
71
+
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,59 @@
1
+ require 'spec_helper'
2
+
3
+ module Arc
4
+ module DataStores
5
+ describe AbstractDataStore do
6
+ before :each do
7
+ @store = AbstractDataStore.new ArcTest.config[:empty]
8
+ @query = "omg"
9
+ end
10
+
11
+ it 'proxies methods to the schema' do
12
+ store = AbstractDataStore.new({})
13
+ schema = ObjectDefinitions::Schema.new(store)
14
+ schema.stub(:[]).and_return(ObjectDefinitions::Table.new :fake_table)
15
+ store.stub!(:schema).and_return(schema)
16
+ store[:fake_table].should be_a(ObjectDefinitions::Table)
17
+ end
18
+
19
+ it 'includes arel compatibility' do
20
+ @store.should be_a(ArelCompatibility)
21
+ end
22
+
23
+ it 'includes quoting module' do
24
+ @store.should be_a(Arc::Quoting)
25
+ end
26
+
27
+ describe '#new' do
28
+ it 'does not define connection creation' do
29
+ store = AbstractDataStore.new ArcTest.config[:sqlite]
30
+ ->{ store.send :with_store }.should raise_error(NotImplementedError)
31
+ end
32
+ end
33
+
34
+ describe 'abstract methods throw NotImplementedError' do
35
+ it '#schema raises not implemented error' do
36
+ ->{ @store.schema }.should raise_error(NotImplementedError)
37
+ end
38
+ it '#create raises not implemented error' do
39
+ ->{ @store.create @query }.should raise_error(NotImplementedError)
40
+ end
41
+ it '#read raises not implemented error' do
42
+ ->{ @store.read @query }.should raise_error(NotImplementedError)
43
+ end
44
+ it '#update raises not implemented error' do
45
+ ->{ @store.update @query }.should raise_error(NotImplementedError)
46
+ end
47
+ it '#destroy raises not implemented error' do
48
+ ->{ @store.destroy @query }.should raise_error(NotImplementedError)
49
+ end
50
+ it '#execute raises not implemented error' do
51
+ ->{ @store.execute @rquery }.should raise_error(NotImplementedError)
52
+ end
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+
59
+
@@ -0,0 +1,79 @@
1
+ require 'spec_helper'
2
+
3
+ module Arc
4
+ module DataStores
5
+ describe 'The data store crud operations' do
6
+
7
+ describe '#create' do
8
+ it 'creates a new record' do
9
+ ArcTest.with_store do |store|
10
+ query = "SELECT * FROM superheros WHERE name = 'green hornet'"
11
+ result = store.read query
12
+ result.size.should == 0
13
+
14
+ store.create "INSERT INTO superheros (name) VALUES('green hornet');"
15
+ store.read(query).size.should == 1
16
+
17
+ #cleanup
18
+ store.destroy "DELETE FROM superheros where name = 'green hornet'"
19
+ end
20
+ end
21
+
22
+ it 'returns the record with a populated primary key' do
23
+ ArcTest.with_store do |store|
24
+ result = store.create "INSERT INTO superheros (name) VALUES('green lantern')"
25
+ result[:id].should_not be_nil
26
+ result[:name].should == 'green lantern'
27
+ #cleanup
28
+ store.destroy "DELETE FROM superheros where name = 'green lantern'"
29
+ end
30
+ end
31
+ end
32
+
33
+ describe '#read' do
34
+ it 'reads existing data' do
35
+ heros = ['superman', 'batman', 'spiderman']
36
+ query = "SELECT * FROM superheros"
37
+
38
+ ArcTest.with_store do |store|
39
+ result = store.read query
40
+ result.size.should == 3
41
+ result.each do |h|
42
+ h.should be_a(Hash)
43
+ heros.should include(h[:name])
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#update' do
50
+ it 'updates a record and returns the updated record' do
51
+ ArcTest.with_store do |store|
52
+ query = "UPDATE superheros SET name = 'wussy' WHERE name = 'batman'"
53
+ result = store.update query
54
+ batman = store.read "SELECT * from superheros WHERE name = 'batman'"
55
+ batman.size.should == 0
56
+ batman.should be_a(Enumerable)
57
+ batman = store.read "SELECT * from superheros WHERE name = 'wussy'"
58
+ batman.first[:name].should == 'wussy'
59
+ end
60
+ end
61
+ end
62
+
63
+ describe '#destroy' do
64
+ it 'deletes a record' do
65
+ ArcTest.with_store do |store|
66
+ query = "SELECT * FROM superheros WHERE name = 'batman'"
67
+ batman = store.read query
68
+ batman.first[:name].should == 'batman'
69
+ store.destroy "DELETE FROM superheros WHERE name = 'batman'"
70
+ batman = store.read query
71
+ batman.size.should == 0
72
+ batman.should be_a(Enumerable)
73
+ end
74
+ end
75
+ end
76
+
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,47 @@
1
+ require 'spec_helper'
2
+
3
+ module Arc
4
+ module DataStores
5
+ module ObjectDefinitions
6
+ describe "All the Schemas!" do
7
+ it 'lists the table names' do
8
+ ArcTest.with_store do |store|
9
+ store.schema.table_names.should == [:superheros]
10
+ end
11
+ end
12
+
13
+ it 'provides a Table object for each table' do
14
+ ArcTest.with_store do |store|
15
+ heros = store[:superheros]
16
+ heros.should be_a(Table)
17
+ heros.column_names.should include(:id)
18
+ heros.column_names.should include(:name)
19
+ end
20
+ end
21
+
22
+ it 'provides a Column object for each column' do
23
+ ArcTest.with_store do |store|
24
+ heros = store[:superheros]
25
+ id = heros[:id]
26
+ id.should be_a(Column)
27
+ id.pk?.should be_true
28
+ id.allows_null?.should be_false
29
+ id.default.should be_nil
30
+ id.name.should == "id"
31
+ id.type.should == :integer
32
+
33
+ #name column
34
+ name = heros[:name]
35
+ name.should be_a(Column)
36
+ name.pk?.should be_false
37
+ name.allows_null?.should be_false
38
+ name.default.should be_nil
39
+ name.name.should == "name"
40
+ name.type.should == :varchar
41
+ end
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+ require 'arc/data_stores/mysql/store'
3
+
4
+ describe Arc::DataStores::MysqlDataStore do
5
+ describe "#schema" do
6
+ it 'is an instance of Arc::DataStores::MysqlSchema' do
7
+ store = Arc::DataStores::MysqlDataStore.new ArcTest.config[:mysql]
8
+ store.schema.should be_a(Arc::DataStores::ObjectDefinitions::MysqlSchema)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+ require 'arc/data_stores/postgres/store'
3
+
4
+ describe Arc::DataStores::PostgresDataStore do
5
+ describe "#schema" do
6
+ it 'is an instance of Arc::DataStores::PostgresSchema' do
7
+ store = Arc::DataStores::PostgresDataStore.new ArcTest.config[:Postgres]
8
+ store.schema.should be_a(Arc::DataStores::ObjectDefinitions::PostgresSchema)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ require 'spec_helper'
2
+ require 'arc/data_stores/sqlite/store'
3
+
4
+ describe Arc::DataStores::SqliteDataStore do
5
+ describe "#schema" do
6
+ it 'is an instance of Arc::DataStores::SqliteSchema' do
7
+ store = Arc::DataStores::SqliteDataStore.new(:database => ":memory:")
8
+ store.schema.should be_a(Arc::DataStores::ObjectDefinitions::SqliteSchema)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ module Arc
4
+ describe DataStores do
5
+ it 'extends Q::Dispatcher' do
6
+ DataStores.should be_a(Q::Dispatcher)
7
+ end
8
+ it "specifies 'DataStore' as the constant_suffix" do
9
+ DataStores.instance_variable_get(:@constant_suffix).should == "DataStore"
10
+ end
11
+ it "specifies 'arc/data_stores/%s_data_store' as the require_pattern" do
12
+ DataStores.instance_variable_get(:@require_pattern).should == "arc/data_stores/%s/store.rb"
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,97 @@
1
+ require 'spec_helper'
2
+
3
+ module Arc
4
+ describe Quoting do
5
+ describe '#quote' do
6
+ def quoter
7
+ @quoter ||= Class.new { include Quoting }.new
8
+ end
9
+ it 'quotes a column name' do
10
+ quoter.quote_column('my_column').should == '"my_column"'
11
+ end
12
+ it 'quotes a table name' do
13
+ t = 'my_table'
14
+ quoter.should_receive(:quote_column_name).with(t)
15
+ quoter.quote_table(t)
16
+ end
17
+ it 'should throw an exception if it cannot find a convertible class' do
18
+ ->{ quoter.quote(Class.new.new) }.should raise_error(Quoting::CannotCastValueError)
19
+ end
20
+ it 'should wrap the symbol using single quotes' do
21
+ quoter.quote(:superman).should == "'superman'"
22
+ quoter.quote('superman', Symbol).should == "'superman'"
23
+ end
24
+ it 'quotes a string' do
25
+ quoter.quote("\\").should == "'\\\\'"
26
+ quoter.quote("'").should == "''''"
27
+ quoter.quote("my%String", String).should == "'my%String'"
28
+ end
29
+ it 'quotes a date object' do
30
+ date = Date.today
31
+ fmt = '%Y-%m-%d'
32
+ quoter.quote(date).should == "'#{date.strftime fmt}'"
33
+ quoter.quote(date.strftime(fmt), Date).should == "'#{date.strftime fmt}'"
34
+ end
35
+ it 'quotes a time object' do
36
+ time = Time.now
37
+ fmt = '%Y-%m-%d %H:%M:%S'
38
+ quoter.quote(time).should == "'#{time.strftime fmt}'"
39
+ quoter.quote(time.strftime(fmt), Time).should == "'#{time.strftime fmt}'"
40
+ end
41
+ it 'quotes a fixnum' do
42
+ fixnum = 10
43
+ quoter.quote(fixnum).should == fixnum.to_s
44
+ quoter.quote(fixnum.to_s, Fixnum).should == fixnum.to_s
45
+ quoter.quote(fixnum.to_s, nil)
46
+ end
47
+ it 'quotes a bignum' do
48
+ bignum = 1<<100
49
+ quoter.quote(bignum).should == bignum.to_s
50
+ quoter.quote(bignum.to_s, Bignum).should == bignum.to_s
51
+ end
52
+ it 'quotes a float' do
53
+ float = 1.2
54
+ quoter.quote(float).should == float.to_s
55
+ quoter.quote(float, Float).should == float.to_s
56
+ end
57
+ it 'quotes a class name' do
58
+ klass = String
59
+ quoter.quote(klass).should == "'String'"
60
+ end
61
+ it 'quotes boolean values' do
62
+ quoter.quote(true, :boolean).should == "'t'"
63
+ quoter.quote(false, :boolean).should == "'f'"
64
+ end
65
+ it 'quotes an object based on column type' do
66
+ superman = "superman"
67
+ ArcTest.with_store do |store|
68
+ c = store[:superheros][:name]
69
+ quoter.quote(superman, c).should == "'superman'"
70
+ c = store[:superheros][:id]
71
+ quoter.quote(10, c).should == '10'
72
+ end
73
+ end
74
+ it 'quotes a bigdecimal' do
75
+ big_decimal = BigDecimal.new((1 << 100).to_s)
76
+ quoter.quote(big_decimal).should == big_decimal.to_s('F')
77
+ quoter.quote(big_decimal.to_s('F'), BigDecimal).should == big_decimal.to_s('F')
78
+ end
79
+ it 'quotes nil' do
80
+ quoter.quote(nil).should == 'NULL'
81
+ quoter.quote('NULL', NilClass).should == 'NULL'
82
+ quoter.quote(nil, NilClass).should == 'NULL'
83
+ end
84
+ it 'quotes true' do
85
+ quoter.quote(true).should == "'t'"
86
+ quoter.quote('true', TrueClass).should == "'t'"
87
+ end
88
+ it 'quotes false' do
89
+ quoter.quote(false).should == "'f'"
90
+ quoter.quote('false', FalseClass).should == "'f'"
91
+ end
92
+ it 'escapes and quotes a binary string' do
93
+ quoter.quote("\0%", :binary).should == "'%00%25'"
94
+ end
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,81 @@
1
+ #generate a coverage report
2
+ require 'simplecov'
3
+ SimpleCov.start
4
+
5
+ require 'bundler/setup'
6
+ require 'rspec'
7
+ require 'arc'
8
+ require 'arel'
9
+ require 'q/resource_pool'
10
+
11
+
12
+ RSpec.configure do |config|
13
+ config.after(:all) do
14
+ ArcTest.drop
15
+ end
16
+ end
17
+
18
+ module ArcTest
19
+ DEFAULT_ADAPTER = 'sqlite'
20
+
21
+ class StoreProvider < ResourcePool
22
+ def create_resource
23
+ Arc::DataStores[ArcTest.adapter].new ArcTest.current_config
24
+ end
25
+ end
26
+
27
+ class << self
28
+
29
+ def config_key
30
+ @config_key ||= (ENV['ARC_ENV'] ||= ArcTest::DEFAULT_ADAPTER).to_sym
31
+ end
32
+
33
+ def file_root
34
+ @file_root ||= "#{File.dirname __FILE__}/support/schemas"
35
+ end
36
+
37
+ def config
38
+ @config ||= YAML::load(File.read "#{File.dirname __FILE__}/support/config.yml").symbolize_keys!
39
+ end
40
+
41
+ def drop
42
+ return unless @schema_loaded
43
+ @drop_ddl ||= File.read "#{file_root}/drop_#{config_key}.sql"
44
+ provider.with_resource { |store| store.schema.execute_ddl @drop_ddl }
45
+ @schema_loaded = false
46
+ end
47
+
48
+ def load_schema
49
+ return if @schema_loaded
50
+ @ddl ||= File.read "#{file_root}/#{config_key}.sql"
51
+ provider.with_resource { |store| store.schema.execute_ddl @ddl }
52
+ @schema_loaded = true
53
+ end
54
+
55
+ def reset_schema
56
+ drop
57
+ load_schema
58
+ end
59
+
60
+ def with_store
61
+ reset_schema
62
+ provider.with_resource do |store|
63
+ yield store
64
+ end
65
+ end
66
+
67
+ def current_config
68
+ config[config_key]
69
+ end
70
+
71
+ def adapter
72
+ current_config[:adapter].to_sym
73
+ end
74
+
75
+ private
76
+ def provider
77
+ @provider ||= StoreProvider.new nil
78
+ end
79
+ end
80
+
81
+ end