activerecord-nulldb-adapter 0.3.0 → 0.3.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f69f1b8bd9e94574231d49a3331d7450898dbf53
4
- data.tar.gz: 30c4eee10acc87ad0cb5506aa9e7ea152d757e61
3
+ metadata.gz: 7989a037f4a78914709a6bc164c42354f4d708ac
4
+ data.tar.gz: 19d7c505c54bff50938ded3876c4950950024dd6
5
5
  SHA512:
6
- metadata.gz: ef9146cce2f44f0ce28f41a82c8d0267b87a80683495d0db646af723a12203a57260c33027426f15e621b188ddb06ce00444d35a64a01a279ff013e0cd2a2ff9
7
- data.tar.gz: b26bfde72d5f8f9b50e27c9d1400633825f951db515f71465f8f1f9fb433ac7f3affdc9448821c931ba0855ccfdd5b83766ee6e1f08486de71b8ad59a11ae444
6
+ metadata.gz: 0f95ca035463bfd3930316ab3f2267a5db786a3a03cdc628a306a7369be037d7ee200a126e50fa8e82c87dffca1eaaf0f1e4f1b89a406fea263cc90b1d9fec8b
7
+ data.tar.gz: eb74c28351efcf56dd5f70b5c1de440866fb1d569a94821ec551d426e986b2a577c2039342fd060003ac25d28a55206a9c76dfa322da8b7b34f7cb8198fd1dcd
data/Appraisals CHANGED
@@ -1,4 +1,5 @@
1
1
  appraise "activerecord-2.3" do
2
+ gem 'iconv', :platforms => :ruby
2
3
  gem "activerecord", "~> 2.3.0"
3
4
  end
4
5
 
data/CHANGES.md CHANGED
@@ -1,3 +1,8 @@
1
+ 0.3.1 (2014-02-17)
2
+ -----------
3
+ - Removes accidental dependency on iconv. Fixing JRuby support.
4
+
5
+
1
6
  0.3.0 (2014-01-31)
2
7
  -----------
3
8
  - Drops 1.8.7 support.
data/Gemfile CHANGED
@@ -2,11 +2,6 @@ source "https://rubygems.org"
2
2
 
3
3
  gem 'activerecord', '>= 2.0.0'
4
4
 
5
- platforms :ruby_20, :ruby_21 do
6
- gem 'iconv'
7
- gem 'coveralls', :group => :test, :require => false
8
- end
9
-
10
5
  group :development, :test do
11
6
  gem 'spec'
12
7
  gem 'rspec', '>= 1.2.9'
@@ -16,4 +11,5 @@ end
16
11
  group :development do
17
12
  gem 'jeweler'
18
13
  gem 'appraisal', :github => 'thoughtbot/appraisal'
14
+ gem 'simplecov', :require => false
19
15
  end
data/README.rdoc CHANGED
@@ -137,11 +137,11 @@ nothing will be saved.
137
137
  == Who
138
138
 
139
139
  NullDB was originally written by Avdi Grimm <mailto:avdi@avdi.org>.
140
- It is currently maintained by {Myron Marston}[http://github.com/myronmarston].
140
+ It is currently maintained by {Bram de Vries}[https://github.com/blaet].
141
141
 
142
142
  == Where
143
143
 
144
- * Homepage: http://github.com/nulldb/nulldb
144
+ * Homepage: https://github.com/nulldb/nulldb
145
145
 
146
146
  == License
147
147
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.1
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: activerecord-nulldb-adapter 0.3.0 ruby lib
5
+ # stub: activerecord-nulldb-adapter 0.3.1 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "activerecord-nulldb-adapter"
9
- s.version = "0.3.0"
9
+ s.version = "0.3.1"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Avdi Grimm", "Myron Marston"]
14
- s.date = "2014-01-31"
14
+ s.date = "2014-02-17"
15
15
  s.description = "A database backend that translates database interactions into no-ops. Using NullDB enables you to test your model business logic - including after_save hooks - without ever touching a real database."
16
16
  s.email = "myron.marston@gmail.com"
17
17
  s.extra_rdoc_files = [
@@ -34,10 +34,20 @@ Gem::Specification.new do |s|
34
34
  "gemfiles/activerecord_3.2.gemfile",
35
35
  "gemfiles/activerecord_4.0.gemfile",
36
36
  "lib/active_record/connection_adapters/nulldb_adapter.rb",
37
+ "lib/active_record/connection_adapters/nulldb_adapter/checkpoint.rb",
38
+ "lib/active_record/connection_adapters/nulldb_adapter/column.rb",
39
+ "lib/active_record/connection_adapters/nulldb_adapter/configuration.rb",
40
+ "lib/active_record/connection_adapters/nulldb_adapter/core.rb",
41
+ "lib/active_record/connection_adapters/nulldb_adapter/empty_result.rb",
42
+ "lib/active_record/connection_adapters/nulldb_adapter/index_definition.rb",
43
+ "lib/active_record/connection_adapters/nulldb_adapter/null_object.rb",
44
+ "lib/active_record/connection_adapters/nulldb_adapter/statement.rb",
45
+ "lib/active_record/connection_adapters/nulldb_adapter/table_definition.rb",
37
46
  "lib/activerecord-nulldb-adapter.rb",
38
47
  "lib/nulldb.rb",
39
48
  "lib/nulldb/arel_compiler.rb",
40
49
  "lib/nulldb/core.rb",
50
+ "lib/nulldb/extensions.rb",
41
51
  "lib/nulldb/rails.rb",
42
52
  "lib/nulldb_rspec.rb",
43
53
  "lib/tasks/database.rake",
@@ -47,7 +57,7 @@ Gem::Specification.new do |s|
47
57
  s.homepage = "http://github.com/nulldb/nulldb"
48
58
  s.licenses = ["MIT"]
49
59
  s.rubyforge_project = "nulldb"
50
- s.rubygems_version = "2.2.0"
60
+ s.rubygems_version = "2.2.2"
51
61
  s.summary = "The Null Object pattern as applied to ActiveRecord database adapters"
52
62
 
53
63
  if s.respond_to? :specification_version then
@@ -55,29 +65,29 @@ Gem::Specification.new do |s|
55
65
 
56
66
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
57
67
  s.add_runtime_dependency(%q<activerecord>, [">= 2.0.0"])
58
- s.add_runtime_dependency(%q<iconv>, [">= 0"])
59
68
  s.add_development_dependency(%q<spec>, [">= 0"])
60
69
  s.add_development_dependency(%q<rspec>, [">= 1.2.9"])
61
70
  s.add_development_dependency(%q<rake>, [">= 0"])
62
71
  s.add_development_dependency(%q<jeweler>, [">= 0"])
63
72
  s.add_development_dependency(%q<appraisal>, [">= 0"])
73
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
64
74
  else
65
75
  s.add_dependency(%q<activerecord>, [">= 2.0.0"])
66
- s.add_dependency(%q<iconv>, [">= 0"])
67
76
  s.add_dependency(%q<spec>, [">= 0"])
68
77
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
69
78
  s.add_dependency(%q<rake>, [">= 0"])
70
79
  s.add_dependency(%q<jeweler>, [">= 0"])
71
80
  s.add_dependency(%q<appraisal>, [">= 0"])
81
+ s.add_dependency(%q<simplecov>, [">= 0"])
72
82
  end
73
83
  else
74
84
  s.add_dependency(%q<activerecord>, [">= 2.0.0"])
75
- s.add_dependency(%q<iconv>, [">= 0"])
76
85
  s.add_dependency(%q<spec>, [">= 0"])
77
86
  s.add_dependency(%q<rspec>, [">= 1.2.9"])
78
87
  s.add_dependency(%q<rake>, [">= 0"])
79
88
  s.add_dependency(%q<jeweler>, [">= 0"])
80
89
  s.add_dependency(%q<appraisal>, [">= 0"])
90
+ s.add_dependency(%q<simplecov>, [">= 0"])
81
91
  end
82
92
  end
83
93
 
@@ -2,6 +2,7 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
+ gem "iconv", :platforms=>:ruby
5
6
  gem "activerecord", "~> 2.3.0"
6
7
 
7
8
  group :development, :test do
@@ -13,9 +14,5 @@ end
13
14
  group :development do
14
15
  gem "jeweler"
15
16
  gem "appraisal", :github=>"thoughtbot/appraisal"
16
- end
17
-
18
- platforms :ruby_20, :ruby_21 do
19
- gem "iconv"
20
- gem "coveralls", :group=>:test, :require=>false
17
+ gem "simplecov", :require=>false
21
18
  end
@@ -13,9 +13,5 @@ end
13
13
  group :development do
14
14
  gem "jeweler"
15
15
  gem "appraisal", :github=>"thoughtbot/appraisal"
16
- end
17
-
18
- platforms :ruby_20, :ruby_21 do
19
- gem "iconv"
20
- gem "coveralls", :group=>:test, :require=>false
16
+ gem "simplecov", :require=>false
21
17
  end
@@ -13,9 +13,5 @@ end
13
13
  group :development do
14
14
  gem "jeweler"
15
15
  gem "appraisal", :github=>"thoughtbot/appraisal"
16
- end
17
-
18
- platforms :ruby_20, :ruby_21 do
19
- gem "iconv"
20
- gem "coveralls", :group=>:test, :require=>false
16
+ gem "simplecov", :require=>false
21
17
  end
@@ -13,9 +13,5 @@ end
13
13
  group :development do
14
14
  gem "jeweler"
15
15
  gem "appraisal", :github=>"thoughtbot/appraisal"
16
- end
17
-
18
- platforms :ruby_20, :ruby_21 do
19
- gem "iconv"
20
- gem "coveralls", :group=>:test, :require=>false
16
+ gem "simplecov", :require=>false
21
17
  end
@@ -13,9 +13,5 @@ end
13
13
  group :development do
14
14
  gem "jeweler"
15
15
  gem "appraisal", :github=>"thoughtbot/appraisal"
16
- end
17
-
18
- platforms :ruby_20, :ruby_21 do
19
- gem "iconv"
20
- gem "coveralls", :group=>:test, :require=>false
16
+ gem "simplecov", :require=>false
21
17
  end
@@ -2,382 +2,20 @@ require 'logger'
2
2
  require 'stringio'
3
3
  require 'singleton'
4
4
  require 'pathname'
5
+
5
6
  require 'active_support'
6
7
  require 'active_record/connection_adapters/abstract_adapter'
7
- require 'nulldb/core'
8
-
9
- unless respond_to?(:tap)
10
- class Object
11
- def tap
12
- yield self
13
- self
14
- end
15
- end
16
- end
17
-
18
- unless respond_to?(:try)
19
- class Object
20
- def try(*a, &b)
21
- if a.empty? && block_given?
22
- yield self
23
- else
24
- __send__(*a, &b)
25
- end
26
- end
27
- end
28
-
29
- class NilClass
30
- def try(*args); nil; end
31
- end
32
- end
33
-
34
- class ActiveRecord::Base
35
- # Instantiate a new NullDB connection. Used by ActiveRecord internally.
36
- def self.nulldb_connection(config)
37
- ActiveRecord::ConnectionAdapters::NullDBAdapter.new(config)
38
- end
39
- end
40
-
41
-
42
- module ActiveRecord
43
- # Just make sure you have the latest version of your schema
44
- class Schema < Migration
45
- def self.define(info={}, &block)
46
- instance_eval(&block)
47
- end
48
- end
49
- end
50
-
51
-
52
- class ActiveRecord::ConnectionAdapters::NullDBAdapter <
53
- ActiveRecord::ConnectionAdapters::AbstractAdapter
54
-
55
- class Column < ::ActiveRecord::ConnectionAdapters::Column
56
- private
57
-
58
- def simplified_type(field_type)
59
- type = super
60
- type = :integer if type.nil? && sql_type == :primary_key
61
- type
62
- end
63
- end
64
-
65
- class Statement
66
- attr_reader :entry_point, :content
67
-
68
- def initialize(entry_point, content = "")
69
- @entry_point, @content = entry_point, content
70
- end
71
-
72
- def ==(other)
73
- self.entry_point == other.entry_point
74
- end
75
- end
76
-
77
- class Checkpoint < Statement
78
- def initialize
79
- super(:checkpoint, "")
80
- end
81
-
82
- def ==(other)
83
- self.class == other.class
84
- end
85
- end
86
-
87
- TableDefinition = ActiveRecord::ConnectionAdapters::TableDefinition
88
-
89
- class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders)
90
- end
91
-
92
- class NullObject
93
- def method_missing(*args, &block)
94
- nil
95
- end
96
-
97
- def to_a
98
- []
99
- end
100
- end
101
-
102
- class EmptyResult < Array
103
- attr_writer :columns
104
- def rows
105
- []
106
- end
107
-
108
- def column_types
109
- columns.map{|col| col.type}
110
- end
111
-
112
- def columns
113
- @columns ||= []
114
- end
115
- end
116
-
117
- # A convenience method for integratinginto RSpec. See README for example of
118
- # use.
119
- def self.insinuate_into_spec(config)
120
- config.before :all do
121
- ActiveRecord::Base.establish_connection(:adapter => :nulldb)
122
- end
123
-
124
- config.after :all do
125
- ActiveRecord::Base.establish_connection(:test)
126
- end
127
- end
128
-
129
- # Recognized options:
130
- #
131
- # [+:schema+] path to the schema file, relative to Rails.root
132
- def initialize(config={})
133
- @log = StringIO.new
134
- @logger = Logger.new(@log)
135
- @last_unique_id = 0
136
- @tables = {'schema_info' => new_table_definition(nil)}
137
- @indexes = Hash.new { |hash, key| hash[key] = [] }
138
- @schema_path = config.fetch(:schema){ "db/schema.rb" }
139
- @config = config.merge(:adapter => :nulldb)
140
- super(nil, @logger)
141
- @visitor = Arel::Visitors::ToSql.new self if defined?(Arel::Visitors::ToSql)
142
- end
143
-
144
- # A log of every statement that has been "executed" by this connection adapter
145
- # instance.
146
- def execution_log
147
- (@execution_log ||= [])
148
- end
149
-
150
- # A log of every statement that has been "executed" since the last time
151
- # #checkpoint! was called, or since the connection was created.
152
- def execution_log_since_checkpoint
153
- checkpoint_index = @execution_log.rindex(Checkpoint.new)
154
- checkpoint_index = checkpoint_index ? checkpoint_index + 1 : 0
155
- @execution_log[(checkpoint_index..-1)]
156
- end
157
-
158
- # Inserts a checkpoint in the log. See also #execution_log_since_checkpoint.
159
- def checkpoint!
160
- self.execution_log << Checkpoint.new
161
- end
162
-
163
- def adapter_name
164
- "NullDB"
165
- end
166
-
167
- def supports_migrations?
168
- true
169
- end
170
-
171
- def create_table(table_name, options = {})
172
- table_definition = new_table_definition(self, table_name, options.delete(:temporary), options)
173
-
174
- unless options[:id] == false
175
- table_definition.primary_key(options[:primary_key] || "id")
176
- end
177
8
 
178
- yield table_definition if block_given?
179
-
180
- @tables[table_name] = table_definition
181
- end
182
-
183
- def add_index(table_name, column_names, options = {})
184
- index_name, index_type, ignore = add_index_options(table_name, column_names, options)
185
- @indexes[table_name] << IndexDefinition.new(table_name, index_name, (index_type == 'UNIQUE'), column_names, [], [])
186
- end
187
-
188
- unless instance_methods.include? :add_index_options
189
- def add_index_options(table_name, column_name, options = {})
190
- column_names = Array.wrap(column_name)
191
- index_name = index_name(table_name, :column => column_names)
192
-
193
- if Hash === options # legacy support, since this param was a string
194
- index_type = options[:unique] ? "UNIQUE" : ""
195
- index_name = options[:name].to_s if options.key?(:name)
196
- else
197
- index_type = options
198
- end
199
-
200
- if index_name.length > index_name_length
201
- raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters"
202
- end
203
- if index_name_exists?(table_name, index_name, false)
204
- raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
205
- end
206
- index_columns = quoted_columns_for_index(column_names, options).join(", ")
207
-
208
- [index_name, index_type, index_columns]
209
- end
210
- end
211
-
212
- unless instance_methods.include? :index_name_exists?
213
- def index_name_exists?(table_name, index_name, default)
214
- return default unless respond_to?(:indexes)
215
- index_name = index_name.to_s
216
- indexes(table_name).detect { |i| i.name == index_name }
217
- end
218
- end
219
-
220
- def add_fk_constraint(*args)
221
- # NOOP
222
- end
223
-
224
- def add_pk_constraint(*args)
225
- # NOOP
226
- end
227
-
228
- # Retrieve the table names defined by the schema
229
- def tables
230
- @tables.keys.map(&:to_s)
231
- end
232
-
233
- # Retrieve table columns as defined by the schema
234
- def columns(table_name, name = nil)
235
- if @tables.size <= 1
236
- ActiveRecord::Migration.verbose = false
237
- schema_path = if Pathname(@schema_path).absolute?
238
- @schema_path
239
- else
240
- File.join(NullDB.configuration.project_root, @schema_path)
241
- end
242
- Kernel.load(schema_path)
243
- end
244
-
245
- if table = @tables[table_name]
246
- table.columns.map do |col_def|
247
- ActiveRecord::ConnectionAdapters::NullDBAdapter::Column.new(
248
- col_def.name.to_s,
249
- col_def.default,
250
- col_def.type,
251
- col_def.null
252
- )
253
- end
254
- else
255
- []
256
- end
257
- end
258
-
259
- # Retrieve table indexes as defined by the schema
260
- def indexes(table_name, name = nil)
261
- @indexes[table_name]
262
- end
263
-
264
- def execute(statement, name = nil)
265
- self.execution_log << Statement.new(entry_point, statement)
266
- NullObject.new
267
- end
268
-
269
- def exec_query(statement, name = 'SQL', binds = [])
270
- self.execution_log << Statement.new(entry_point, statement)
271
- EmptyResult.new
272
- end
273
-
274
- def select_rows(statement, name = nil)
275
- [].tap do
276
- self.execution_log << Statement.new(entry_point, statement)
277
- end
278
- end
279
-
280
- def insert(statement, name = nil, primary_key = nil, object_id = nil, sequence_name = nil, binds = [])
281
- (object_id || next_unique_id).tap do
282
- with_entry_point(:insert) do
283
- super(statement, name, primary_key, object_id, sequence_name)
284
- end
285
- end
286
- end
287
- alias :create :insert
288
-
289
- def update(statement, name=nil, binds = [])
290
- with_entry_point(:update) do
291
- super(statement, name)
292
- end
293
- end
294
-
295
- def delete(statement, name=nil, binds = [])
296
- with_entry_point(:delete) do
297
- super(statement, name)
298
- end
299
- end
300
-
301
- def select_all(statement, name=nil, binds = [])
302
- with_entry_point(:select_all) do
303
- super(statement, name)
304
- end
305
- end
306
-
307
- def select_one(statement, name=nil, binds = [])
308
- with_entry_point(:select_one) do
309
- super(statement, name)
310
- end
311
- end
312
-
313
- def select_value(statement, name=nil, binds = [])
314
- with_entry_point(:select_value) do
315
- super(statement, name)
316
- end
317
- end
318
-
319
- def select_values(statement, name=nil)
320
- with_entry_point(:select_values) do
321
- super(statement, name)
322
- end
323
- end
324
-
325
- def primary_key(table_name)
326
- columns(table_name).detect { |col| col.sql_type == :primary_key }.try(:name)
327
- end
328
-
329
- protected
330
-
331
- def select(statement, name = nil, binds = [])
332
- EmptyResult.new.tap do |r|
333
- r.columns = columns_for(name)
334
- self.execution_log << Statement.new(entry_point, statement)
335
- end
336
- end
337
-
338
- private
339
-
340
- def columns_for(table_name)
341
- table_def = @tables[table_name]
342
- table_def ? table_def.columns : []
343
- end
344
-
345
- def next_unique_id
346
- @last_unique_id += 1
347
- end
348
-
349
- def with_entry_point(method)
350
- if entry_point.nil?
351
- with_thread_local_variable(:entry_point, method) do
352
- yield
353
- end
354
- else
355
- yield
356
- end
357
- end
358
-
359
- def entry_point
360
- Thread.current[:entry_point]
361
- end
362
-
363
- def with_thread_local_variable(name, value)
364
- old_value = Thread.current[name]
365
- Thread.current[name] = value
366
- begin
367
- yield
368
- ensure
369
- Thread.current[name] = old_value
370
- end
371
- end
9
+ require 'nulldb/core'
10
+ require 'nulldb/extensions'
11
+
12
+ require 'active_record/connection_adapters/nulldb_adapter/core'
13
+ require 'active_record/connection_adapters/nulldb_adapter/statement'
14
+ require 'active_record/connection_adapters/nulldb_adapter/checkpoint'
15
+ require 'active_record/connection_adapters/nulldb_adapter/column'
16
+ require 'active_record/connection_adapters/nulldb_adapter/configuration'
17
+ require 'active_record/connection_adapters/nulldb_adapter/empty_result'
18
+ require 'active_record/connection_adapters/nulldb_adapter/index_definition'
19
+ require 'active_record/connection_adapters/nulldb_adapter/null_object'
20
+ require 'active_record/connection_adapters/nulldb_adapter/table_definition'
372
21
 
373
- def new_table_definition(adapter = nil, table_name = nil, is_temporary = nil, options = {})
374
- case ::ActiveRecord::VERSION::MAJOR
375
- when 4
376
- TableDefinition.new(native_database_types, table_name, is_temporary, options)
377
- when 2,3
378
- TableDefinition.new(adapter)
379
- else
380
- raise "Unsupported ActiveRecord version #{::ActiveRecord::VERSION::STRING}"
381
- end
382
- end
383
- end
@@ -0,0 +1,13 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class Checkpoint < Statement
4
+ def initialize
5
+ super(:checkpoint, "")
6
+ end
7
+
8
+ def ==(other)
9
+ self.class == other.class
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,11 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+ class Column < ::ActiveRecord::ConnectionAdapters::Column
3
+ private
4
+
5
+ def simplified_type(field_type)
6
+ type = super
7
+ type = :integer if type.nil? && sql_type == :primary_key
8
+ type
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class Configuration < Struct.new(:project_root); end
4
+
5
+ end
@@ -0,0 +1,270 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter < ActiveRecord::ConnectionAdapters::AbstractAdapter
2
+
3
+ # A convenience method for integratinginto RSpec. See README for example of
4
+ # use.
5
+ def self.insinuate_into_spec(config)
6
+ config.before :all do
7
+ ActiveRecord::Base.establish_connection(:adapter => :nulldb)
8
+ end
9
+
10
+ config.after :all do
11
+ ActiveRecord::Base.establish_connection(:test)
12
+ end
13
+ end
14
+
15
+ # Recognized options:
16
+ #
17
+ # [+:schema+] path to the schema file, relative to Rails.root
18
+ def initialize(config={})
19
+ @log = StringIO.new
20
+ @logger = Logger.new(@log)
21
+ @last_unique_id = 0
22
+ @tables = {'schema_info' => new_table_definition(nil)}
23
+ @indexes = Hash.new { |hash, key| hash[key] = [] }
24
+ @schema_path = config.fetch(:schema){ "db/schema.rb" }
25
+ @config = config.merge(:adapter => :nulldb)
26
+ super(nil, @logger)
27
+ @visitor = Arel::Visitors::ToSql.new self if defined?(Arel::Visitors::ToSql)
28
+ end
29
+
30
+ # A log of every statement that has been "executed" by this connection adapter
31
+ # instance.
32
+ def execution_log
33
+ (@execution_log ||= [])
34
+ end
35
+
36
+ # A log of every statement that has been "executed" since the last time
37
+ # #checkpoint! was called, or since the connection was created.
38
+ def execution_log_since_checkpoint
39
+ checkpoint_index = @execution_log.rindex(Checkpoint.new)
40
+ checkpoint_index = checkpoint_index ? checkpoint_index + 1 : 0
41
+ @execution_log[(checkpoint_index..-1)]
42
+ end
43
+
44
+ # Inserts a checkpoint in the log. See also #execution_log_since_checkpoint.
45
+ def checkpoint!
46
+ self.execution_log << Checkpoint.new
47
+ end
48
+
49
+ def adapter_name
50
+ "NullDB"
51
+ end
52
+
53
+ def supports_migrations?
54
+ true
55
+ end
56
+
57
+ def create_table(table_name, options = {})
58
+ table_definition = new_table_definition(self, table_name, options.delete(:temporary), options)
59
+
60
+ unless options[:id] == false
61
+ table_definition.primary_key(options[:primary_key] || "id")
62
+ end
63
+
64
+ yield table_definition if block_given?
65
+
66
+ @tables[table_name] = table_definition
67
+ end
68
+
69
+ def add_index(table_name, column_names, options = {})
70
+ column_names = Array.wrap(column_names).map(&:to_s)
71
+ index_name, index_type, ignore = add_index_options(table_name, column_names, options)
72
+ @indexes[table_name] << IndexDefinition.new(table_name, index_name, (index_type == 'UNIQUE'), column_names, [], [])
73
+ end
74
+
75
+ unless instance_methods.include? :add_index_options
76
+ def add_index_options(table_name, column_name, options = {})
77
+ column_names = Array.wrap(column_name)
78
+ index_name = index_name(table_name, :column => column_names)
79
+
80
+ if Hash === options # legacy support, since this param was a string
81
+ index_type = options[:unique] ? "UNIQUE" : ""
82
+ index_name = options[:name].to_s if options.key?(:name)
83
+ else
84
+ index_type = options
85
+ end
86
+
87
+ if index_name.length > index_name_length
88
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' is too long; the limit is #{index_name_length} characters"
89
+ end
90
+ if index_name_exists?(table_name, index_name, false)
91
+ raise ArgumentError, "Index name '#{index_name}' on table '#{table_name}' already exists"
92
+ end
93
+ index_columns = quoted_columns_for_index(column_names, options).join(", ")
94
+
95
+ [index_name, index_type, index_columns]
96
+ end
97
+ end
98
+
99
+ unless instance_methods.include? :index_name_exists?
100
+ def index_name_exists?(table_name, index_name, default)
101
+ return default unless respond_to?(:indexes)
102
+ index_name = index_name.to_s
103
+ indexes(table_name).detect { |i| i.name == index_name }
104
+ end
105
+ end
106
+
107
+ def add_fk_constraint(*args)
108
+ # NOOP
109
+ end
110
+
111
+ def add_pk_constraint(*args)
112
+ # NOOP
113
+ end
114
+
115
+ # Retrieve the table names defined by the schema
116
+ def tables
117
+ @tables.keys.map(&:to_s)
118
+ end
119
+
120
+ # Retrieve table columns as defined by the schema
121
+ def columns(table_name, name = nil)
122
+ if @tables.size <= 1
123
+ ActiveRecord::Migration.verbose = false
124
+ schema_path = if Pathname(@schema_path).absolute?
125
+ @schema_path
126
+ else
127
+ File.join(NullDB.configuration.project_root, @schema_path)
128
+ end
129
+ Kernel.load(schema_path)
130
+ end
131
+
132
+ if table = @tables[table_name]
133
+ table.columns.map do |col_def|
134
+ ActiveRecord::ConnectionAdapters::NullDBAdapter::Column.new(
135
+ col_def.name.to_s,
136
+ col_def.default,
137
+ col_def.type,
138
+ col_def.null
139
+ )
140
+ end
141
+ else
142
+ []
143
+ end
144
+ end
145
+
146
+ # Retrieve table indexes as defined by the schema
147
+ def indexes(table_name, name = nil)
148
+ @indexes[table_name]
149
+ end
150
+
151
+ def execute(statement, name = nil)
152
+ self.execution_log << Statement.new(entry_point, statement)
153
+ NullObject.new
154
+ end
155
+
156
+ def exec_query(statement, name = 'SQL', binds = [])
157
+ self.execution_log << Statement.new(entry_point, statement)
158
+ EmptyResult.new
159
+ end
160
+
161
+ def select_rows(statement, name = nil)
162
+ [].tap do
163
+ self.execution_log << Statement.new(entry_point, statement)
164
+ end
165
+ end
166
+
167
+ def insert(statement, name = nil, primary_key = nil, object_id = nil, sequence_name = nil, binds = [])
168
+ (object_id || next_unique_id).tap do
169
+ with_entry_point(:insert) do
170
+ super(statement, name, primary_key, object_id, sequence_name)
171
+ end
172
+ end
173
+ end
174
+ alias :create :insert
175
+
176
+ def update(statement, name=nil, binds = [])
177
+ with_entry_point(:update) do
178
+ super(statement, name)
179
+ end
180
+ end
181
+
182
+ def delete(statement, name=nil, binds = [])
183
+ with_entry_point(:delete) do
184
+ super(statement, name)
185
+ end
186
+ end
187
+
188
+ def select_all(statement, name=nil, binds = [])
189
+ with_entry_point(:select_all) do
190
+ super(statement, name)
191
+ end
192
+ end
193
+
194
+ def select_one(statement, name=nil, binds = [])
195
+ with_entry_point(:select_one) do
196
+ super(statement, name)
197
+ end
198
+ end
199
+
200
+ def select_value(statement, name=nil, binds = [])
201
+ with_entry_point(:select_value) do
202
+ super(statement, name)
203
+ end
204
+ end
205
+
206
+ def select_values(statement, name=nil)
207
+ with_entry_point(:select_values) do
208
+ super(statement, name)
209
+ end
210
+ end
211
+
212
+ def primary_key(table_name)
213
+ columns(table_name).detect { |col| col.sql_type == :primary_key }.try(:name)
214
+ end
215
+
216
+ protected
217
+
218
+ def select(statement, name = nil, binds = [])
219
+ EmptyResult.new.tap do |r|
220
+ r.columns = columns_for(name)
221
+ self.execution_log << Statement.new(entry_point, statement)
222
+ end
223
+ end
224
+
225
+ private
226
+
227
+ def columns_for(table_name)
228
+ table_def = @tables[table_name]
229
+ table_def ? table_def.columns : []
230
+ end
231
+
232
+ def next_unique_id
233
+ @last_unique_id += 1
234
+ end
235
+
236
+ def with_entry_point(method)
237
+ if entry_point.nil?
238
+ with_thread_local_variable(:entry_point, method) do
239
+ yield
240
+ end
241
+ else
242
+ yield
243
+ end
244
+ end
245
+
246
+ def entry_point
247
+ Thread.current[:entry_point]
248
+ end
249
+
250
+ def with_thread_local_variable(name, value)
251
+ old_value = Thread.current[name]
252
+ Thread.current[name] = value
253
+ begin
254
+ yield
255
+ ensure
256
+ Thread.current[name] = old_value
257
+ end
258
+ end
259
+
260
+ def new_table_definition(adapter = nil, table_name = nil, is_temporary = nil, options = {})
261
+ case ::ActiveRecord::VERSION::MAJOR
262
+ when 4
263
+ TableDefinition.new(native_database_types, table_name, is_temporary, options)
264
+ when 2,3
265
+ TableDefinition.new(adapter)
266
+ else
267
+ raise "Unsupported ActiveRecord version #{::ActiveRecord::VERSION::STRING}"
268
+ end
269
+ end
270
+ end
@@ -0,0 +1,18 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class EmptyResult < Array
4
+ attr_writer :columns
5
+ def rows
6
+ []
7
+ end
8
+
9
+ def column_types
10
+ columns.map{|col| col.type}
11
+ end
12
+
13
+ def columns
14
+ @columns ||= []
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,5 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders); end
4
+
5
+ end
@@ -0,0 +1,13 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class NullObject
4
+ def method_missing(*args, &block)
5
+ nil
6
+ end
7
+
8
+ def to_a
9
+ []
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,15 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ class Statement
4
+ attr_reader :entry_point, :content
5
+
6
+ def initialize(entry_point, content = "")
7
+ @entry_point, @content = entry_point, content
8
+ end
9
+
10
+ def ==(other)
11
+ self.entry_point == other.entry_point
12
+ end
13
+ end
14
+
15
+ end
@@ -0,0 +1,5 @@
1
+ class ActiveRecord::ConnectionAdapters::NullDBAdapter
2
+
3
+ TableDefinition = ActiveRecord::ConnectionAdapters::TableDefinition
4
+
5
+ end
@@ -0,0 +1,41 @@
1
+ unless respond_to?(:tap)
2
+ class Object
3
+ def tap
4
+ yield self
5
+ self
6
+ end
7
+ end
8
+ end
9
+
10
+ unless respond_to?(:try)
11
+ class Object
12
+ def try(*a, &b)
13
+ if a.empty? && block_given?
14
+ yield self
15
+ else
16
+ __send__(*a, &b)
17
+ end
18
+ end
19
+ end
20
+
21
+ class NilClass
22
+ def try(*args); nil; end
23
+ end
24
+ end
25
+
26
+ class ActiveRecord::Base
27
+ # Instantiate a new NullDB connection. Used by ActiveRecord internally.
28
+ def self.nulldb_connection(config)
29
+ ActiveRecord::ConnectionAdapters::NullDBAdapter.new(config)
30
+ end
31
+ end
32
+
33
+
34
+ module ActiveRecord
35
+ # Just make sure you have the latest version of your schema
36
+ class Schema < Migration
37
+ def self.define(info={}, &block)
38
+ instance_eval(&block)
39
+ end
40
+ end
41
+ end
data/spec/nulldb_spec.rb CHANGED
@@ -1,9 +1,9 @@
1
1
  require 'rubygems'
2
2
 
3
- # Use Coveralls/SimpleCov when available
3
+ # Optional simplecov loading
4
4
  begin
5
- require 'coveralls'
6
- Coveralls.wear!
5
+ require 'simplecov'
6
+ SimpleCov.start
7
7
  rescue LoadError
8
8
  end
9
9
 
@@ -82,7 +82,7 @@ describe "NullDB" do
82
82
  t.integer :widget_id
83
83
  end
84
84
 
85
- add_index "employees", ["name"], :name => "index_employees_on_name"
85
+ add_index "employees", :name, :name => "index_employees_on_name"
86
86
  add_index "employees", ["employee_number"], :name => "index_employees_on_employee_number", :unique => true
87
87
  add_index "employees_widgets", ["employee_id", "widget_id"], :name => "my_index"
88
88
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-nulldb-adapter
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Avdi Grimm
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-01-31 00:00:00.000000000 Z
12
+ date: 2014-02-17 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
@@ -26,13 +26,13 @@ dependencies:
26
26
  - !ruby/object:Gem::Version
27
27
  version: 2.0.0
28
28
  - !ruby/object:Gem::Dependency
29
- name: iconv
29
+ name: spec
30
30
  requirement: !ruby/object:Gem::Requirement
31
31
  requirements:
32
32
  - - '>='
33
33
  - !ruby/object:Gem::Version
34
34
  version: '0'
35
- type: :runtime
35
+ type: :development
36
36
  prerelease: false
37
37
  version_requirements: !ruby/object:Gem::Requirement
38
38
  requirements:
@@ -40,35 +40,35 @@ dependencies:
40
40
  - !ruby/object:Gem::Version
41
41
  version: '0'
42
42
  - !ruby/object:Gem::Dependency
43
- name: spec
43
+ name: rspec
44
44
  requirement: !ruby/object:Gem::Requirement
45
45
  requirements:
46
46
  - - '>='
47
47
  - !ruby/object:Gem::Version
48
- version: '0'
48
+ version: 1.2.9
49
49
  type: :development
50
50
  prerelease: false
51
51
  version_requirements: !ruby/object:Gem::Requirement
52
52
  requirements:
53
53
  - - '>='
54
54
  - !ruby/object:Gem::Version
55
- version: '0'
55
+ version: 1.2.9
56
56
  - !ruby/object:Gem::Dependency
57
- name: rspec
57
+ name: rake
58
58
  requirement: !ruby/object:Gem::Requirement
59
59
  requirements:
60
60
  - - '>='
61
61
  - !ruby/object:Gem::Version
62
- version: 1.2.9
62
+ version: '0'
63
63
  type: :development
64
64
  prerelease: false
65
65
  version_requirements: !ruby/object:Gem::Requirement
66
66
  requirements:
67
67
  - - '>='
68
68
  - !ruby/object:Gem::Version
69
- version: 1.2.9
69
+ version: '0'
70
70
  - !ruby/object:Gem::Dependency
71
- name: rake
71
+ name: jeweler
72
72
  requirement: !ruby/object:Gem::Requirement
73
73
  requirements:
74
74
  - - '>='
@@ -82,7 +82,7 @@ dependencies:
82
82
  - !ruby/object:Gem::Version
83
83
  version: '0'
84
84
  - !ruby/object:Gem::Dependency
85
- name: jeweler
85
+ name: appraisal
86
86
  requirement: !ruby/object:Gem::Requirement
87
87
  requirements:
88
88
  - - '>='
@@ -96,7 +96,7 @@ dependencies:
96
96
  - !ruby/object:Gem::Version
97
97
  version: '0'
98
98
  - !ruby/object:Gem::Dependency
99
- name: appraisal
99
+ name: simplecov
100
100
  requirement: !ruby/object:Gem::Requirement
101
101
  requirements:
102
102
  - - '>='
@@ -134,10 +134,20 @@ files:
134
134
  - gemfiles/activerecord_3.2.gemfile
135
135
  - gemfiles/activerecord_4.0.gemfile
136
136
  - lib/active_record/connection_adapters/nulldb_adapter.rb
137
+ - lib/active_record/connection_adapters/nulldb_adapter/checkpoint.rb
138
+ - lib/active_record/connection_adapters/nulldb_adapter/column.rb
139
+ - lib/active_record/connection_adapters/nulldb_adapter/configuration.rb
140
+ - lib/active_record/connection_adapters/nulldb_adapter/core.rb
141
+ - lib/active_record/connection_adapters/nulldb_adapter/empty_result.rb
142
+ - lib/active_record/connection_adapters/nulldb_adapter/index_definition.rb
143
+ - lib/active_record/connection_adapters/nulldb_adapter/null_object.rb
144
+ - lib/active_record/connection_adapters/nulldb_adapter/statement.rb
145
+ - lib/active_record/connection_adapters/nulldb_adapter/table_definition.rb
137
146
  - lib/activerecord-nulldb-adapter.rb
138
147
  - lib/nulldb.rb
139
148
  - lib/nulldb/arel_compiler.rb
140
149
  - lib/nulldb/core.rb
150
+ - lib/nulldb/extensions.rb
141
151
  - lib/nulldb/rails.rb
142
152
  - lib/nulldb_rspec.rb
143
153
  - lib/tasks/database.rake
@@ -163,7 +173,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
163
173
  version: '0'
164
174
  requirements: []
165
175
  rubyforge_project: nulldb
166
- rubygems_version: 2.2.0
176
+ rubygems_version: 2.2.2
167
177
  signing_key:
168
178
  specification_version: 4
169
179
  summary: The Null Object pattern as applied to ActiveRecord database adapters