activerecord-nulldb-adapter 0.3.0 → 0.3.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.
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