fixation 0.1.1 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +19 -18
- data/lib/fixation.rb +80 -33
- data/lib/fixation/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ca6857caa4389c5c93c2be0ad4ddcd79bdd6895b
|
4
|
+
data.tar.gz: 3130d2d5b400e597fb04c57fd80a8bb0449e8cc1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f589e251617bf4efcb8e6818c35b1e471a06f07ce0dfc605edfa8ed4eeb1f779f29205cd844d609bffdfc22052f331d8cc234ff5d1f9fc158d7ff55752659fba
|
7
|
+
data.tar.gz: db7f49521e7a588e71a0d672c168053eba47193b3ada05d9fbc34687465d898bf7aa0f984bcf635c37fdc2cff8f189782ff4a8db3d184f5b4eba2fd1621715f9
|
data/README.md
CHANGED
@@ -2,8 +2,7 @@
|
|
2
2
|
|
3
3
|
This gem will precompile the SQL statements needed to clear and repopulate your test tables with fixtures when the app boots under spring, so that spec startup just needs to run a small number of multi-row SQL statements to prepare for run. This takes around 1/10th the time as a normal fixture load.
|
4
4
|
|
5
|
-
|
6
|
-
|
5
|
+
Like ActiveRecord's normal fixture implementation, Fixation will load the model classes in order to use metadata about associations and enums. But since Fixation is run at the time spring starts, Fixation will then 'reload' rails (the same way spring does), so you can change your model classes and re-run tests without having to restart spring.
|
7
6
|
|
8
7
|
## Installation
|
9
8
|
|
@@ -23,39 +22,41 @@ Or install it yourself as:
|
|
23
22
|
|
24
23
|
Then, make an initializer:
|
25
24
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
25
|
+
```ruby
|
26
|
+
if Rails.env.test? && Fixation.running_under_spring?
|
27
|
+
Rails.application.config.after_initialize do
|
28
|
+
Fixation.preload_for_spring
|
29
|
+
end
|
30
|
+
end
|
31
|
+
```
|
32
32
|
|
33
33
|
And run `spring stop` so this gets picked up.
|
34
34
|
|
35
35
|
Finally, open up your spec_helper.rb, and find the current `global_fixtures` setting:
|
36
36
|
|
37
|
-
|
37
|
+
```ruby
|
38
|
+
config.global_fixtures = :all
|
39
|
+
```
|
38
40
|
|
39
41
|
Change that to [] so that ActiveRecord doesn't load the fixtures again itself, and load the Fixation module:
|
40
42
|
|
41
|
-
|
42
|
-
|
43
|
+
```ruby
|
44
|
+
config.global_fixtures = []
|
45
|
+
config.include Fixation.fixture_methods
|
46
|
+
```
|
43
47
|
|
44
48
|
## Usage
|
45
49
|
|
46
|
-
|
50
|
+
Simply use run your tests under spring.
|
47
51
|
|
48
|
-
|
52
|
+
bundle exec spring spec/models/my_spec.rb
|
49
53
|
|
50
54
|
## Limitations
|
51
55
|
|
52
|
-
|
56
|
+
You'll need to run rake tasks like `db:create` and `db:test:prepare` the normal way (without spring), because if the database doesn't exist or the schema isn't loaded, the initializer above will asplode.
|
53
57
|
|
54
|
-
|
55
|
-
* the fixture filenames must match the database table names directly - whereas ActiveRecord actually assumes the filenames are underscored versions of the model class names, and it uses that class's configured table name
|
56
|
-
* when using the identify syntax to set association foreign keys, you must use the name that corresponds to the foreign key attribute (for example, `parent: sue` if you want to set the `parent_id` field to the appropriate value for the fixture called `sue`) - whereas ActiveRecord accepts the name of the association (`lead_carer: sue`) even if it uses a different foreign key name (`belongs_to :lead_carer, :foreign_key => :parent_id`)
|
58
|
+
Not all features of regular ActiveRecord fixtures are supported:
|
57
59
|
* HABTM support has not been implemented (does anyone use HABTM these days?)
|
58
|
-
* enums are not known
|
59
60
|
|
60
61
|
## Contributing
|
61
62
|
|
data/lib/fixation.rb
CHANGED
@@ -14,6 +14,20 @@ module Fixation
|
|
14
14
|
@table_name = table_name
|
15
15
|
@connection = connection
|
16
16
|
@now = now
|
17
|
+
|
18
|
+
@klass_name = @table_name.classify
|
19
|
+
begin
|
20
|
+
@klass = @klass_name.constantize
|
21
|
+
@klass = nil unless @klass < ActiveRecord::Base
|
22
|
+
rescue NameError
|
23
|
+
ActiveRecord::Base.logger.warn "couldn't load #{@klass_name} for fixture table #{table_name}: #{$!}"
|
24
|
+
end
|
25
|
+
|
26
|
+
if @klass
|
27
|
+
@primary_key = @klass.primary_key
|
28
|
+
@record_timestamps = @klass.record_timestamps
|
29
|
+
@inheritance_column = @klass.inheritance_column
|
30
|
+
end
|
17
31
|
end
|
18
32
|
|
19
33
|
def columns_hash
|
@@ -49,12 +63,8 @@ module Fixation
|
|
49
63
|
|
50
64
|
def embellish_fixture(name, attributes, columns_hash)
|
51
65
|
# populate the primary key column, if not already set
|
52
|
-
if columns_hash[
|
53
|
-
attributes[
|
54
|
-
end
|
55
|
-
|
56
|
-
if columns_hash['uuid'] && !attributes.has_key?('uuid')
|
57
|
-
attributes['uuid'] = Fixation.identify(name, columns_hash['uuid'].type)
|
66
|
+
if @primary_key && columns_hash[@primary_key] && !attributes.has_key?(@primary_key)
|
67
|
+
attributes[@primary_key] = Fixation.identify(name, columns_hash[@primary_key].type)
|
58
68
|
end
|
59
69
|
|
60
70
|
# substitute $LABEL into all string values
|
@@ -63,27 +73,50 @@ module Fixation
|
|
63
73
|
end
|
64
74
|
|
65
75
|
# populate any timestamp columns, if not already set
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
76
|
+
if @record_timestamps
|
77
|
+
%w(created_at updated_at).each do |column_name|
|
78
|
+
attributes[column_name] = now if columns_hash[column_name] && !attributes.has_key?(column_name)
|
79
|
+
end
|
80
|
+
%w(created_at updated_at).each do |column_name|
|
81
|
+
attributes[column_name] = now.to_date if columns_hash[column_name] && !attributes.has_key?(column_name)
|
82
|
+
end
|
71
83
|
end
|
72
84
|
|
73
|
-
# convert
|
85
|
+
# convert enum names to values
|
86
|
+
@klass.defined_enums.each do |name, values|
|
87
|
+
attributes[name] = values.fetch(attributes[name], attributes[name]) if attributes.has_key?(name)
|
88
|
+
end if @klass.respond_to?(:defined_enums)
|
89
|
+
|
90
|
+
# convert any association names into the identity column equivalent - following code from activerecord's fixtures.rb
|
74
91
|
nonexistant_columns = attributes.keys - columns_hash.keys
|
75
|
-
nonexistant_columns.each do |column_name|
|
76
|
-
if columns_hash["#{column_name}_id"]
|
77
|
-
value = attributes.delete(column_name)
|
78
92
|
|
79
|
-
|
80
|
-
|
81
|
-
|
93
|
+
if @klass && nonexistant_columns.present?
|
94
|
+
# If STI is used, find the correct subclass for association reflection
|
95
|
+
reflection_class =
|
96
|
+
if attributes.include?(@inheritance_column)
|
97
|
+
attributes[@inheritance_column].constantize rescue @klass
|
98
|
+
else
|
99
|
+
@klass
|
82
100
|
end
|
83
101
|
|
84
|
-
|
85
|
-
|
86
|
-
|
102
|
+
nonexistant_columns.each do |column_name|
|
103
|
+
association = reflection_class._reflections[column_name.to_sym]
|
104
|
+
|
105
|
+
if association.nil?
|
106
|
+
raise ActiveRecord::Fixture::FormatError, "No column named #{column_name} found in table #{table_name}"
|
107
|
+
elsif association.macro != :belongs_to
|
108
|
+
raise ActiveRecord::Fixture::FormatError, "Association #{column_name} in table #{table_name} has type #{association.macro}, which is not currently supported"
|
109
|
+
else
|
110
|
+
value = attributes.delete(column_name)
|
111
|
+
|
112
|
+
if association.options[:polymorphic] && value.is_a?(String) && value.sub!(/\s*\(([^\)]*)\)\s*$/, "")
|
113
|
+
# support polymorphic belongs_to as "label (Type)"
|
114
|
+
attributes[association.foreign_type] = $1
|
115
|
+
end
|
116
|
+
|
117
|
+
fk_name = (association.options[:foreign_key] || "#{association.name}_id").to_s
|
118
|
+
attributes[fk_name] = value ? ActiveRecord::FixtureSet.identify(value) : value
|
119
|
+
end
|
87
120
|
end
|
88
121
|
end
|
89
122
|
end
|
@@ -163,9 +196,11 @@ module Fixation
|
|
163
196
|
end
|
164
197
|
|
165
198
|
def apply_fixtures(connection = ActiveRecord::Base.connection)
|
166
|
-
|
167
|
-
|
168
|
-
|
199
|
+
connection.transaction do
|
200
|
+
@statements.each do |table_name, table_statements|
|
201
|
+
table_statements.each do |statement|
|
202
|
+
connection.execute(statement)
|
203
|
+
end
|
169
204
|
end
|
170
205
|
end
|
171
206
|
end
|
@@ -223,17 +258,13 @@ module Fixation
|
|
223
258
|
cattr_accessor :paths
|
224
259
|
self.paths = %w(test/fixtures spec/fixtures)
|
225
260
|
|
226
|
-
def self.
|
227
|
-
|
261
|
+
def self.preload_for_spring
|
262
|
+
build_fixtures
|
263
|
+
unload_models!
|
264
|
+
end
|
228
265
|
|
266
|
+
def self.build_fixtures
|
229
267
|
@fixtures = Fixtures.new
|
230
|
-
|
231
|
-
subclasses_after = ActiveRecord::Base.subclasses
|
232
|
-
|
233
|
-
unless subclasses_after.size == subclasses_before.size
|
234
|
-
new_subclasses = subclasses_after - subclasses_before
|
235
|
-
puts "warning: #{new_subclasses.to_sentence} #{new_subclasses.size == 1 ? 'was' : 'were'} auto-loaded while loading fixtures. #{new_subclasses.size == 1 ? 'this class' : 'these classes'} may not reload properly."
|
236
|
-
end
|
237
268
|
end
|
238
269
|
|
239
270
|
def self.apply_fixtures
|
@@ -259,4 +290,20 @@ module Fixation
|
|
259
290
|
ActiveRecord::FixtureSet.identify(label, column_type)
|
260
291
|
end
|
261
292
|
end
|
293
|
+
|
294
|
+
def self.running_under_spring?
|
295
|
+
defined?(Spring::Application)
|
296
|
+
end
|
297
|
+
|
298
|
+
# reloads Rails (using the code from Spring) in order to unload the model classes that get
|
299
|
+
# auto-loaded when we read the fixture definitions.
|
300
|
+
def self.unload_models!
|
301
|
+
# Rails 5.1 forward-compat. AD::R is deprecated to AS::R in Rails 5.
|
302
|
+
if defined? ActiveSupport::Reloader
|
303
|
+
Rails.application.reloader.reload!
|
304
|
+
else
|
305
|
+
ActionDispatch::Reloader.cleanup!
|
306
|
+
ActionDispatch::Reloader.prepare!
|
307
|
+
end
|
308
|
+
end
|
262
309
|
end
|
data/lib/fixation/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fixation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Will Bryant
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-04-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|